Compare commits

..

9 Commits

Author SHA1 Message Date
w0rp
4c3bd8a84f Revert "Merge pull request #1487 from rhysd/fix-1472"
This reverts commit 67b71653f5.
2018-04-17 13:33:47 +01:00
w0rp
d1224a05c4 #1497 Tolerate important ALE variables being undefined for some reason when viewing buffers like git commits 2018-04-12 21:04:15 +01:00
w0rp
0e4a7a7187 Fix #1495 - Fall back to /bin/sh when shell=pwsh 2018-04-12 21:04:02 +01:00
w0rp
36a3932ce8 Fix #1492 - Make pylint error parsing work on Windows 2018-04-10 15:20:02 +01:00
w0rp
67b71653f5 Merge pull request #1487 from rhysd/fix-1472
pylint: Move to the buffer's directory before running pylint command
2018-04-09 18:15:28 +01:00
aspidiets
229da9b8ef Fix #1424 - Make the brittany fixer work 2018-04-08 17:39:51 +01:00
w0rp
7e4372bd1f Use the --stdin-filename option for textlint, so configuration files will be discovered better 2018-04-05 15:12:24 +01:00
w0rp
f6fc1edcdc Fix config and executable issues with the textlint linter 2018-04-05 15:09:41 +01:00
w0rp
6e5a74285c Merge pull request #1455 from Christian-Gibbons/flawfinder_cpp_severity_fix
Fix Flawfinder for C++
2018-04-05 15:07:12 +01:00
1184 changed files with 10498 additions and 44488 deletions

View File

@@ -5,11 +5,6 @@ clone_depth: 10
# Use the directory C:\testplugin so test directories will mostly work. # Use the directory C:\testplugin so test directories will mostly work.
clone_folder: C:\testplugin clone_folder: C:\testplugin
branches:
only:
- master
- /v\d+\.\d+\.(x|\d+)/
# Cache the vim and vader directories between builds. # Cache the vim and vader directories between builds.
cache: cache:
- C:\vim -> .appveyor.yml - C:\vim -> .appveyor.yml

1
.gitattributes vendored
View File

@@ -2,7 +2,6 @@
/CODE_OF_CONDUCT.md export-ignore /CODE_OF_CONDUCT.md export-ignore
/CONTRIBUTING.md export-ignore /CONTRIBUTING.md export-ignore
/Dockerfile export-ignore /Dockerfile export-ignore
/ISSUE_TEMPLATE export-ignore
/ISSUE_TEMPLATE.md export-ignore /ISSUE_TEMPLATE.md export-ignore
/Makefile export-ignore /Makefile export-ignore
/PULL_REQUEST_TEMPLATE.md export-ignore /PULL_REQUEST_TEMPLATE.md export-ignore

View File

@@ -1,25 +0,0 @@
## Guidelines
Have fun, and work on whatever floats your boat. Take It Easy :tm:.
For help with contributing to ALE, see `:help ale-development` in Vim, or view
the help file online [here](/doc/ale-development.txt).
## Creating Issues
Before creating any issues, please look through the current list of issues and
pull requests, and ensure that the issue hasn't already been reported. If an
issue has already been reported, but you have some new insight, please add
a comment to the existing issue.
Please read the FAQ in the README before creating any issues. A feature
you desire may already exist and be documented, or the FAQ might explain
how to solve a problem you have already.
Please try and describe any issues reported with as much detail as you can
provide about your Vim version, the linter you were trying to run, your
operating system, or any other information you think might be helpful.
Please describe your issue in clear, grammatically correct, and easy to
understand English. You are more likely to see an issue resolved if others
can understand you.

View File

@@ -1,46 +0,0 @@
---
name: Report a bug
labels: bug
about: Report a bug with ALE.
---
<!--
This is the template for reporting ALE bugs. Make sure you try updating ALE
to a more recent version before reporting a bug. Look through existing bug
reports for similar issues before reporting a new one. Don't leave comments
about new bugs in the comment section for old issues.
Make sure to try disabling other plugins and trying to repeat your bug before
reporting it in ALE. Some times problems can arise when two plugins are used
together, but often your issues might be problems with other plugins.
-->
## Information
**VIM version**
<!-- Paste just the first two lines of :version here. -->
Operating System: <!-- Describe your operating system version. -->
## What went wrong
<!-- Describe what went wrong here. Be specific. -->
Something went wrong in specifically this place, and I also searched through both open and closed issues for the same problem before reporting a bug here.
Are you having trouble configuring ALE? Try asking for help on [Stack Exchange](https://vi.stackexchange.com/) or perhaps on [Reddit](https://www.reddit.com/r/vim/) instead. The GitHub issue tracker should be used for reporting bugs or asking for new features.
## Reproducing the bug
<!-- Write a list of steps below. -->
1. I did this.
2. Then this happened.
### :ALEInfo
<!-- Paste the output of :ALEInfo here. Try :ALEInfoToClipboard -->
<!-- Make sure to run :ALEInfo from the buffer where the bug occurred. -->
<!-- Read the output. You might figure out what went wrong yourself. -->

View File

@@ -1,21 +0,0 @@
---
name: Suggest a new linter or fixer
labels: new tool
about: Suggest a new tool ALE can officially integrate with.
---
<!--
Write "Add support for foobar" as the issue title, or similar.
Fill out the details below.
-->
**Name:** foobar
**URL:** https://foo.bar.com
<!--
Write a description of the tool, and add any other information you think might
be helpful. Consider creating a pull request to add support for the tool
yourself.
-->

View File

@@ -1,8 +0,0 @@
---
name: Suggest an improvement
labels: enhancement
about: Suggest some way to improve ALE, or add a new feature.
---
<!-- There's no fixed format for feature requests. Just add your thoughts. -->

View File

@@ -1,13 +0,0 @@
<!--
Before creating a pull request, do the following.
* Read the Contributing guide linked above first.
* Read the documentation that comes with ALE with `:help ale-dev`.
Have fun!
-->
Where are the tests? Have you added tests? Have you updated the tests? Read the
comment above and the documentation referenced in it first. Write tests!
Seriously, read `:help ale-dev` and write tests.

11
.gitignore vendored
View File

@@ -1,11 +1,6 @@
/init.vim
/doc/tags
.*
!.editorconfig !.editorconfig
*.obj *.obj
# Ignore all hidden files everywhere.
# Use `git add -f` to add hidden files.
.*
__pycache__
*.pyc
/doc/tags
/init.vim
/test/ale-info-test-file
tags tags

View File

@@ -2,15 +2,6 @@
sudo: required sudo: required
services: services:
- docker - docker
language: generic language: python
branches:
only:
- master
- /^v\d+\.\d+\.(x|\d+)$/
env:
- OPTIONS=--vim-80-only
- OPTIONS=--vim-81-only
- OPTIONS=--neovim-only
- OPTIONS=--linters-only
script: | script: |
./run-tests -v $OPTIONS ./run-tests

173
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,173 @@
# Contributing to ALE
1. [Guidelines](#guidelines)
2. [Creating Issues](#issues)
3. [Creating Pull Requests](#pull-requests)
1. [Adding a New Linter](#adding-a-new-linter)
2. [Adding New Options](#adding-new-options)
4. [Writing Documentation](#writing-documentation)
1. [Documenting New Linters](#documenting-new-linters)
2. [Editing the Online Documentation](#editing-online-documentation)
3. [Documenting Linter Options](#documenting-linter-options)
5. [In Case of Busses](#in-case-of-busses)
<a name="guidelines"></a>
## 1. Guidelines
Have fun, and work on whatever floats your boat. Take It Easy :tm:.
Don't forget to **write documentation** for whatever it is you are doing.
See the ["Writing Documentation"](#writing-documentation) section.
Remember to write Vader tests for most of the code you write. You can look at
existing Vader tests in the `test` directory for examples.
When writing code, follow the [Google Vimscript Style
Guide](https://google.github.io/styleguide/vimscriptguide.xml), and run `vint
-s` on your files to check for most of what the guide mentions and more. If you
install this plugin (ALE) and install [Vint](https://github.com/Kuniwak/vint), it
will check your code while you type.
<a name="issues"></a>
## 2. Creating Issues
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
issue has already been reported, but you have some new insight, please add
a comment to the existing issue.
Please read the FAQ in the README before creating any issues. A feature
you desire may already exist and be documented, or the FAQ might explain
how to solve a problem you have already.
Please try and describe any issues reported with as much detail as you can
provide about your Vim version, the linter you were trying to run, your
operating system, or any other information you think might be helpful.
Please describe your issue in clear, grammatically correct, and easy to
understand English. You are more likely to see an issue resolved if others
can understand you.
<a name="pull-requests"></a>
## 3. Creating Pull Requests
For code you write, make sure to credit yourself at the top of files you add,
and probably those you modify. You can write some comments at the top of your
VIM files.
```vim
" Author: John Smith <john.smith@gmail.com>
" Description: This file adds support for awesomelinter for the best language ever.
```
If you want to credit multiple authors, you can comma separate them.
```vim
" Author: John Smith <john.smith@gmail.com>, Jane Doe <https://jane-doe.info>
```
<a name="adding-a-new-linter"></a>
### 3.i. Adding a New Linter
If you add a new linter, look for existing handlers first in the
[handlers](autoload/ale/handlers) directory. One of the handlers there may
already be able to handle your lines of output. If you find that your new
linter replicates an existing error handler, consider pulling it up into the
[handlers](autoload/ale/handlers) directory, and use the generic handler in
both places.
When you add a linter, make sure the language for the linter and the linter
itself are present in the table in the [README.md](README.md) file and in the
Vim [help file](doc/ale.txt). The programs and linters should be sorted
alphabetically in the table and list.
<a name="adding-new-options"></a>
### 3.ii. Adding New Options
If you add new options to the plugin, make sure to document those new options
in the [README.md](README.md) file, and also in the [help file](doc/ale.txt).
Follow the format of other options in each. Global options should appear in the
README file, and in the relevant section in the help file. Options specific
to a particular linter should appear in the section for that linter.
Linter options for customizing general argument lists should be named
`g:ale_<filetype>_<linter>_options`, so that all linters can have similar
global variable names.
Any options for linters should be set to some default value so it is always
easy to see what the default is with `:echo g:ale...`.
<a name="writing-documentation"></a>
## 4. Writing Documentation
If you are adding new linters, changing the API, adding new options, etc., you
_must_ write some documentation describing it in the `doc/ale.txt` file. New
linters _must_ be added to the `README.md` file too, so other users can get a
quick overview of the supported tools.
<a name="documenting-new-linters"></a>
### 4.i Documenting New Linters
If you add a new linter to the project, edit the table in the `README.md` file,
and edit the list of linters at the top of the `doc/ale.txt` file. The linters
should be sorted vertically in lexicographic (alphabetical) order by the
programming language name or filetype, and the tools for each language should
be sorted in lexicographic order horizontally. Sorting in this manner is a fair
manner of presenting all of the information in an easy to scan way, without
giving some unfair preference to any particular tool or language.
<a name="editing-online-documentation"></a>
### 4.ii Editing the Online Documentation
The "online documentation" file used for this project lives in `doc/ale.txt`.
This is the file used for generating `:help` text inside Vim itself. There are
some guidelines to follow for this file.
1. Keep all text within a column size of 79 characters, inclusive.
2. Open a section with 79 `=` or `-` characters, for headings and subheadings.
3. Sections should have a _single_ blank line before or after.
4. Between descriptions of variables/functions/commands, use _two_ blank lines.
5. Up-indent the description of a variable/function/command by two spaces.
6. Place tags at the ends of lines, with the final characters on column 79.
All of the tags should line up perfectly on the same column as you scan
down through the document.
7. Keep the table of contents balanced so the longest tag link ends on column
79, and so all links line up perfectly on their first character, on the
left.
<a name="documenting-linter-options"></a>
### 4.iii Documenting Linter Options
For documenting new linter options, please add a new sub-section under the
"Linter Specific Options" section describing all of the global options added
for each linter, and what the default values of the options are. All global
options for linters should be set to some default value. This will allow users
to look up the default value easily by typing `:echo g:ale_...`.
<a name="in-case-of-busses"></a>
## 5. In Case of Busses
Should the principal author of the ALE project and all collaborators with the
required access needed to properly administrate the project on GitHub or any
other website either perish or disappear, whether by tragic traffic accident
or government abduction, etc., action should be taken to ensure that the
project continues. If no one is left to administer the project where it is
hosted, please fork the project and nominate someone capable to administer it.
Preferably, in such an event, a single fork of the project will replace the
original, and life will go on, except the life of whoever vanished, because
then they will probably be dead.
Should w0rp suddenly disappear, then he was probably killed in a traffic
accident, or the government finally decided to kill him and make it look like
suicide. In the latter event, please subvert said government and restore
order to the universe, and ensure peace for mankind.

View File

@@ -1,9 +1,7 @@
FROM tweekmonster/vim-testbed:latest FROM tweekmonster/vim-testbed:latest
RUN install_vim -tag v8.0.0027 -build \ RUN install_vim -tag v8.0.0027 -build \
-tag v8.1.0519 -build \ -tag neovim:v0.1.7 -build
-tag neovim:v0.2.0 -build \
-tag neovim:v0.3.5 -build
ENV PACKAGES="\ ENV PACKAGES="\
bash \ bash \
@@ -14,7 +12,7 @@ ENV PACKAGES="\
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.15 RUN pip install vim-vint==0.3.9
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

28
ISSUE_TEMPLATE.md Normal file
View File

@@ -0,0 +1,28 @@
<!--
This is a template for bug reports. If you want to request a new feature,
you can clear this entire form field and write a short description of what
you want.
-->
## Information
**VIM version**
PASTE JUST THE FIRST TWO LINES OF `:version` HERE.
Operating System: WHAT OS WERE YOU USING?
### :ALEInfo
PASTE OUTPUT OF `:ALEInfo` HERE. YOU CAN TRY `:ALEInfoToClipboard`.
## What went wrong
WRITE WHAT WENT WRONG HERE.
## Reproducing the bug
Steps for repeating the bug:
1. Write a list of steps.
2. Otherwise nobody will fix the bug.

View File

@@ -1,4 +1,4 @@
Copyright (c) 2016-2019, w0rp <devw0rp@gmail.com> Copyright (c) 2016-2018, 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

21
PULL_REQUEST_TEMPLATE.md Normal file
View File

@@ -0,0 +1,21 @@
<!--
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!
-->

467
README.md
View File

@@ -1,13 +1,12 @@
# Asynchronous Lint Engine [![Travis CI Build Status](https://travis-ci.com/dense-analysis/ale.svg?branch=master)](https://travis-ci.com/dense-analysis/ale) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/r0ef1xu8xjmik58d/branch/master?svg=true)](https://ci.appveyor.com/project/dense-analysis/ale) [![Join the chat at https://gitter.im/vim-ale/Lobby](https://badges.gitter.im/vim-ale/Lobby.svg)](https://gitter.im/vim-ale/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) # Asynchronous Lint Engine [![Travis CI Build Status](https://travis-ci.org/w0rp/ale.svg?branch=master)](https://travis-ci.org/w0rp/ale) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/r0ef1xu8xjmik58d/branch/master?svg=true)](https://ci.appveyor.com/project/w0rp/ale)
![ALE Logo by Mark Grealish - https://www.bhalash.com/](https://user-images.githubusercontent.com/3518142/59195920-2c339500-8b85-11e9-9c22-f6b7f69637b8.jpg) ![ALE Logo by Mark Grealish - https://www.bhalash.com/](img/logo.jpg?raw=true)
ALE (Asynchronous Lint Engine) is a plugin providing linting (syntax checking ALE (Asynchronous Lint Engine) is a plugin for providing linting in NeoVim
and semantic errors) in NeoVim 0.2.0+ and Vim 8 while you edit your text files, and Vim 8 while you edit your text files.
and acts as a Vim [Language Server Protocol](https://langserver.org/) client.
<img src="https://user-images.githubusercontent.com/3518142/59195938-3a81b100-8b85-11e9-8e8d-6a601b1db908.gif" alt="A linting example with the darkspectrum color scheme in GVim." title="A linting example with the darkspectrum color scheme in GVim."> ![linting example](img/example.gif?raw=true)
ALE makes use of NeoVim and Vim 8 job control functions and timers to ALE makes use of NeoVim and Vim 8 job control functions and timers to
run linters on the contents of text buffers and return errors as run linters on the contents of text buffers and return errors as
@@ -17,30 +16,8 @@ back to a filesystem.
In other words, this plugin allows you to lint while you type. In other words, this plugin allows you to lint while you type.
ALE offers support for fixing code with command line tools in a non-blocking In addition to linting support, ALE offers some support for fixing code with
manner with the `:ALEFix` feature, supporting tools in many languages, like formatting tools, and some Language Server Protocol and `tsserver` features.
`prettier`, `eslint`, `autopep8`, and more.
ALE acts as a "language client" to support a variety of Language Server Protocol
features, including:
* Diagnostics (via Language Server Protocol linters)
* Go To Definition (`:ALEGoToDefinition`)
* Completion (Built in completion support, or with Deoplete)
* Finding references (`:ALEFindReferences`)
* Hover information (`:ALEHover`)
* Symbol search (`:ALESymbolSearch`)
If you don't care about Language Server Protocol, ALE won't load any of the code
for working with it unless needed. One of ALE's general missions is that you
won't pay for the features that you don't use.
**Help Wanted:** If you would like to help maintain this plugin by managing the
many issues and pull requests that are submitted, please send the author an
email at [dev@w0rp.com](mailto:dev@w0rp.com?subject=Helping%20with%20ALE).
If you enjoy this plugin, feel free to contribute or check out the author's
other content at [w0rp.com](https://w0rp.com).
## Table of Contents ## Table of Contents
@@ -50,14 +27,10 @@ other content at [w0rp.com](https://w0rp.com).
2. [Fixing](#usage-fixing) 2. [Fixing](#usage-fixing)
3. [Completion](#usage-completion) 3. [Completion](#usage-completion)
4. [Go To Definition](#usage-go-to-definition) 4. [Go To Definition](#usage-go-to-definition)
5. [Find References](#usage-find-references)
6. [Hovering](#usage-hover)
7. [Symbol Search](#usage-symbol-search)
3. [Installation](#installation) 3. [Installation](#installation)
1. [Installation with Vim package management](#standard-installation) 1. [Installation with Vim package management](#standard-installation)
2. [Installation with Pathogen](#installation-with-pathogen) 2. [Installation with Pathogen](#installation-with-pathogen)
3. [Installation with Vundle](#installation-with-vundle) 3. [Installation with Vundle](#installation-with-vundle)
4. [Installation with Vim-Plug](#installation-with-vim-plug)
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)
@@ -72,20 +45,130 @@ other content at [w0rp.com](https://w0rp.com).
10. [How can I run linters only when I save files?](#faq-lint-on-save) 10. [How can I run linters only when I save files?](#faq-lint-on-save)
11. [How can I use the quickfix list instead of the loclist?](#faq-quickfix) 11. [How can I use the quickfix list instead of the loclist?](#faq-quickfix)
12. [How can I check JSX files with both stylelint and eslint?](#faq-jsx-stylelint-eslint) 12. [How can I check JSX files with both stylelint and eslint?](#faq-jsx-stylelint-eslint)
13. [How can I check Vue files with ESLint?](#faq-vue-eslint) 13. [Will this plugin eat all of my laptop battery power?](#faq-my-battery-is-sad)
14. [Will this plugin eat all of my laptop battery power?](#faq-my-battery-is-sad) 14. [How can I configure my C or C++ project?](#faq-c-configuration)
15. [How can I configure my C or C++ project?](#faq-c-configuration) 15. [How can I configure ALE differently for different buffers?](#faq-buffer-configuration)
16. [How can I configure ALE differently for different buffers?](#faq-buffer-configuration) 16. [How can I configure the height of the list in which ALE displays errors?](#faq-list-window-height)
17. [How can I configure the height of the list in which ALE displays errors?](#faq-list-window-height)
18. [How can I see what ALE has configured for the current file?](#faq-get-info)
<a name="supported-languages"></a> <a name="supported-languages"></a>
## 1. Supported Languages and Tools ## 1. Supported Languages and Tools
ALE supports a wide variety of languages and tools. See the This plugin supports the following languages and tools. All available
[full list](supported-tools.md) in the tools will be run in combination, so they can be complementary.
[Supported Languages and Tools](supported-tools.md) page.
<!--
Keep the table rows sorted alphabetically by the language name,
and the tools in the tools column sorted alphabetically by the tool
name. That seems to be the fairest way to arrange this table.
Remember to also update doc/ale.txt, which has a similar list with different
formatting.
-->
**Notes:**
* *^ No linters for text or Vim help filetypes are enabled by default.*
* *!! These linters check only files on disk. See `:help ale-lint-file-linters`*
| Language | Tools |
| -------- | ----- |
| ASM | [gcc](https://gcc.gnu.org) |
| Ansible | [ansible-lint](https://github.com/willthames/ansible-lint) |
| API Blueprint | [drafter](https://github.com/apiaryio/drafter) |
| AsciiDoc | [alex](https://github.com/wooorm/alex) !!, [proselint](http://proselint.com/), [redpen](http://redpen.cc/), [write-good](https://github.com/btford/write-good) |
| Awk | [gawk](https://www.gnu.org/software/gawk/)|
| Bash | shell [-n flag](https://www.gnu.org/software/bash/manual/bash.html#index-set), [shellcheck](https://www.shellcheck.net/), [shfmt](https://github.com/mvdan/sh) |
| Bourne Shell | shell [-n flag](http://linux.die.net/man/1/sh), [shellcheck](https://www.shellcheck.net/), [shfmt](https://github.com/mvdan/sh) |
| C | [cppcheck](http://cppcheck.sourceforge.net), [cpplint](https://github.com/google/styleguide/tree/gh-pages/cpplint), [clang](http://clang.llvm.org/), [clangtidy](http://clang.llvm.org/extra/clang-tidy/) !!, [clang-format](https://clang.llvm.org/docs/ClangFormat.html), [flawfinder](https://www.dwheeler.com/flawfinder/), [gcc](https://gcc.gnu.org/) |
| C++ (filetype cpp) | [clang](http://clang.llvm.org/), [clangcheck](http://clang.llvm.org/docs/ClangCheck.html) !!, [clangtidy](http://clang.llvm.org/extra/clang-tidy/) !!, [clang-format](https://clang.llvm.org/docs/ClangFormat.html), [cppcheck](http://cppcheck.sourceforge.net), [cpplint](https://github.com/google/styleguide/tree/gh-pages/cpplint) !!, [flawfinder](https://www.dwheeler.com/flawfinder/), [gcc](https://gcc.gnu.org/) |
| CUDA | [nvcc](http://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html) |
| C# | [mcs](http://www.mono-project.com/docs/about-mono/languages/csharp/) see:`help ale-cs-mcs` for details, [mcsc](http://www.mono-project.com/docs/about-mono/languages/csharp/) !! see:`help ale-cs-mcsc` for details and configuration|
| Chef | [foodcritic](http://www.foodcritic.io/) |
| Clojure | [joker](https://github.com/candid82/joker) |
| CMake | [cmakelint](https://github.com/richq/cmake-lint) |
| CoffeeScript | [coffee](http://coffeescript.org/), [coffeelint](https://www.npmjs.com/package/coffeelint) |
| Crystal | [crystal](https://crystal-lang.org/) !! |
| CSS | [csslint](http://csslint.net/), [prettier](https://github.com/prettier/prettier), [stylelint](https://github.com/stylelint/stylelint) |
| Cython (pyrex filetype) | [cython](http://cython.org/) |
| D | [dmd](https://dlang.org/dmd-linux.html) |
| Dafny | [dafny](https://rise4fun.com/Dafny) !! |
| Dart | [dartanalyzer](https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_cli) !!, [language_server](https://github.com/natebosch/dart_language_server) |
| Dockerfile | [hadolint](https://github.com/hadolint/hadolint) |
| Elixir | [credo](https://github.com/rrrene/credo), [dialyxir](https://github.com/jeremyjh/dialyxir), [dogma](https://github.com/lpil/dogma) !!|
| Elm | [elm-format](https://github.com/avh4/elm-format), [elm-make](https://github.com/elm-lang/elm-make) |
| Erb | [erb](https://apidock.com/ruby/ERB), [erubi](https://github.com/jeremyevans/erubi), [erubis](https://github.com/kwatch/erubis) |
| Erlang | [erlc](http://erlang.org/doc/man/erlc.html), [SyntaxErl](https://github.com/ten0s/syntaxerl) |
| Fish | fish [-n flag](https://linux.die.net/man/1/fish)
| Fortran | [gcc](https://gcc.gnu.org/) |
| Fountain | [proselint](http://proselint.com/) |
| FusionScript | [fusion-lint](https://github.com/RyanSquared/fusionscript) |
| Git Commit Messages | [gitlint](https://github.com/jorisroovers/gitlint) |
| GLSL | [glslang](https://github.com/KhronosGroup/glslang), [glslls](https://github.com/svenstaro/glsl-language-server) |
| Go | [gofmt](https://golang.org/cmd/gofmt/), [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports), [go vet](https://golang.org/cmd/vet/) !!, [golint](https://godoc.org/github.com/golang/lint), [gotype](https://godoc.org/golang.org/x/tools/cmd/gotype) !!, [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 | [eslint](http://eslint.org/), [gqlint](https://github.com/happylinks/gqlint), [prettier](https://github.com/prettier/prettier) |
| Haml | [haml-lint](https://github.com/brigade/haml-lint) |
| Handlebars | [ember-template-lint](https://github.com/rwjblue/ember-template-lint) |
| Haskell | [brittany](https://github.com/lspitzner/brittany), [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), [hfmt](https://github.com/danstiner/hfmt) |
| HTML | [alex](https://github.com/wooorm/alex) !!, [HTMLHint](http://htmlhint.com/), [proselint](http://proselint.com/), [tidy](http://www.html-tidy.org/), [write-good](https://github.com/btford/write-good) |
| Idris | [idris](http://www.idris-lang.org/) |
| Java | [checkstyle](http://checkstyle.sourceforge.net), [javac](http://www.oracle.com/technetwork/java/javase/downloads/index.html), [google-java-format](https://github.com/google/google-java-format) |
| JavaScript | [eslint](http://eslint.org/), [flow](https://flowtype.org/), [jscs](http://jscs.info/), [jshint](http://jshint.com/), [prettier](https://github.com/prettier/prettier), [prettier-eslint](https://github.com/prettier/prettier-eslint), [prettier-standard](https://github.com/sheerun/prettier-standard), [standard](http://standardjs.com/), [xo](https://github.com/sindresorhus/xo)
| JSON | [fixjson](https://github.com/rhysd/fixjson), [jsonlint](http://zaa.ch/jsonlint/), [jq](https://stedolan.github.io/jq/), [prettier](https://github.com/prettier/prettier) |
| Kotlin | [kotlinc](https://kotlinlang.org) !!, [ktlint](https://ktlint.github.io) !! see `:help ale-integration-kotlin` for configuration instructions |
| LaTeX | [alex](https://github.com/wooorm/alex) !!, [chktex](http://www.nongnu.org/chktex/), [lacheck](https://www.ctan.org/pkg/lacheck), [proselint](http://proselint.com/), [redpen](http://redpen.cc/), [vale](https://github.com/ValeLint/vale), [write-good](https://github.com/btford/write-good) |
| Less | [lessc](https://www.npmjs.com/package/less), [prettier](https://github.com/prettier/prettier), [stylelint](https://github.com/stylelint/stylelint) |
| LLVM | [llc](https://llvm.org/docs/CommandGuide/llc.html) |
| Lua | [luac](https://www.lua.org/manual/5.1/luac.html), [luacheck](https://github.com/mpeterv/luacheck) |
| Mail | [alex](https://github.com/wooorm/alex) !!, [proselint](http://proselint.com/), [vale](https://github.com/ValeLint/vale) |
| Make | [checkmake](https://github.com/mrtazz/checkmake) |
| Markdown | [alex](https://github.com/wooorm/alex) !!, [markdownlint](https://github.com/DavidAnson/markdownlint) !!, [mdl](https://github.com/mivok/markdownlint), [prettier](https://github.com/prettier/prettier), [proselint](http://proselint.com/), [redpen](http://redpen.cc/), [remark-lint](https://github.com/wooorm/remark-lint) !!, [textlint](https://textlint.github.io/), [vale](https://github.com/ValeLint/vale), [write-good](https://github.com/btford/write-good) |
| MATLAB | [mlint](https://www.mathworks.com/help/matlab/ref/mlint.html) |
| Nim | [nim check](https://nim-lang.org/docs/nimc.html) !! |
| nix | [nix-instantiate](http://nixos.org/nix/manual/#sec-nix-instantiate) |
| nroff | [alex](https://github.com/wooorm/alex) !!, [proselint](http://proselint.com/), [write-good](https://github.com/btford/write-good)|
| 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-ocaml-merlin` for configuration instructions, [ols](https://github.com/freebroccolo/ocaml-language-server) |
| Perl | [perl -c](https://perl.org/), [perl-critic](https://metacpan.org/pod/Perl::Critic) |
| PHP | [hack](http://hacklang.org/), [hackfmt](https://github.com/facebook/flow/tree/master/hack/hackfmt), [langserver](https://github.com/felixfbecker/php-language-server), [phan](https://github.com/phan/phan) see `:help ale-php-phan` to instructions, [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-cs-fixer](http://cs.sensiolabs.org/) |
| PO | [alex](https://github.com/wooorm/alex) !!, [msgfmt](https://www.gnu.org/software/gettext/manual/html_node/msgfmt-Invocation.html), [proselint](http://proselint.com/), [write-good](https://github.com/btford/write-good) |
| Pod | [alex](https://github.com/wooorm/alex) !!, [proselint](http://proselint.com/), [write-good](https://github.com/btford/write-good) |
| Pony | [ponyc](https://github.com/ponylang/ponyc) |
| proto | [protoc-gen-lint](https://github.com/ckaznocha/protoc-gen-lint) |
| Pug | [pug-lint](https://github.com/pugjs/pug-lint) |
| Puppet | [puppet](https://puppet.com), [puppet-lint](https://puppet-lint.com) |
| Python | [autopep8](https://github.com/hhatto/autopep8), [flake8](http://flake8.pycqa.org/en/latest/), [isort](https://github.com/timothycrosley/isort), [mypy](http://mypy-lang.org/), [prospector](http://github.com/landscapeio/prospector), [pycodestyle](https://github.com/PyCQA/pycodestyle), [pyls](https://github.com/palantir/python-language-server), [pylint](https://www.pylint.org/) !!, [yapf](https://github.com/google/yapf) |
| QML | [qmllint](https://github.com/qt/qtdeclarative/tree/5.11/tools/qmllint) |
| R | [lintr](https://github.com/jimhester/lintr) |
| ReasonML | [merlin](https://github.com/the-lambda-church/merlin) see `:help ale-reasonml-ols` for configuration instructions, [ols](https://github.com/freebroccolo/ocaml-language-server), [refmt](https://github.com/reasonml/reason-cli) |
| reStructuredText | [alex](https://github.com/wooorm/alex) !!, [proselint](http://proselint.com/), [redpen](http://redpen.cc/), [rstcheck](https://github.com/myint/rstcheck), [vale](https://github.com/ValeLint/vale), [write-good](https://github.com/btford/write-good) |
| Re:VIEW | [redpen](http://redpen.cc/) |
| RPM spec | [rpmlint](https://github.com/rpm-software-management/rpmlint) (disabled by default; see `:help ale-integration-spec`) |
| Ruby | [brakeman](http://brakemanscanner.org/) !!, [rails_best_practices](https://github.com/flyerhzm/rails_best_practices) !!, [reek](https://github.com/troessner/reek), [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org), [rufo](https://github.com/ruby-formatter/rufo) |
| Rust | cargo !! (see `:help ale-integration-rust` for configuration instructions), [rls](https://github.com/rust-lang-nursery/rls), [rustc](https://www.rust-lang.org/), [rustfmt](https://github.com/rust-lang-nursery/rustfmt) |
| SASS | [sass-lint](https://www.npmjs.com/package/sass-lint), [stylelint](https://github.com/stylelint/stylelint) |
| SCSS | [prettier](https://github.com/prettier/prettier), [sass-lint](https://www.npmjs.com/package/sass-lint), [scss-lint](https://github.com/brigade/scss-lint), [stylelint](https://github.com/stylelint/stylelint) |
| Scala | [scalac](http://scala-lang.org), [scalastyle](http://www.scalastyle.org) |
| Slim | [slim-lint](https://github.com/sds/slim-lint) |
| SML | [smlnj](http://www.smlnj.org/) |
| Solidity | [solhint](https://github.com/protofire/solhint), [solium](https://github.com/duaraghav8/Solium) |
| Stylus | [stylelint](https://github.com/stylelint/stylelint) |
| SQL | [sqlint](https://github.com/purcell/sqlint) |
| Swift | [swiftlint](https://github.com/realm/SwiftLint), [swiftformat](https://github.com/nicklockwood/SwiftFormat) |
| Tcl | [nagelfar](http://nagelfar.sourceforge.net) !! |
| Terraform | [tflint](https://github.com/wata727/tflint) |
| Texinfo | [alex](https://github.com/wooorm/alex) !!, [proselint](http://proselint.com/), [write-good](https://github.com/btford/write-good)|
| Text^ | [alex](https://github.com/wooorm/alex) !!, [proselint](http://proselint.com/), [redpen](http://redpen.cc/), [textlint](https://textlint.github.io/), [vale](https://github.com/ValeLint/vale), [write-good](https://github.com/btford/write-good) |
| Thrift | [thrift](http://thrift.apache.org/) |
| TypeScript | [eslint](http://eslint.org/), [prettier](https://github.com/prettier/prettier), [tslint](https://github.com/palantir/tslint), tsserver, typecheck |
| Verilog | [iverilog](https://github.com/steveicarus/iverilog), [verilator](http://www.veripool.org/projects/verilator/wiki/Intro) |
| Vim | [vint](https://github.com/Kuniwak/vint) |
| Vim help^ | [alex](https://github.com/wooorm/alex) !!, [proselint](http://proselint.com/), [write-good](https://github.com/btford/write-good) |
| Vue | [prettier](https://github.com/prettier/prettier) |
| XHTML | [alex](https://github.com/wooorm/alex) !!, [proselint](http://proselint.com/), [write-good](https://github.com/btford/write-good) |
| XML | [xmllint](http://xmlsoft.org/xmllint.html) |
| YAML | [swaglint](https://github.com/byCedric/swaglint), [yamllint](https://yamllint.readthedocs.io/) |
<a name="usage"></a> <a name="usage"></a>
@@ -105,55 +188,31 @@ new buffers or as you make edits to your files.
The behaviour of linting can be configured with a variety of options, The behaviour of linting can be configured with a variety of options,
documented in [the Vim help file](doc/ale.txt). For more information on the 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-integration-options` for options specified to particular linters. ale-linter-options` for options specified to particular linters.
<a name="usage-fixing"></a> <a name="usage-fixing"></a>
### 2.ii Fixing ### 2.ii Fixing
ALE can fix files with the `ALEFix` command. Functions need to be configured ALE can fix files with the `ALEFix` command. Functions need to be configured
either in each buffer with a `b:ale_fixers`, or globally with `g:ale_fixers`. for different filetypes with the `g:ale_fixers` variable. For example, the
following code can be used to fix JavaScript code with ESLint:
The recommended way to configure fixers is to define a List in an ftplugin file.
```vim ```vim
" In ~/.vim/ftplugin/javascript.vim, or somewhere similar. " 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.
" Fix files with prettier, and then ESLint.
let b:ale_fixers = ['prettier', 'eslint']
" Equivalent to the above.
let b:ale_fixers = {'javascript': ['prettier', 'eslint']}
```
You can also configure your fixers from vimrc using `g:ale_fixers`, before or
after ALE has been loaded.
A `*` in place of the filetype will apply a List of fixers to all files which
do not match some filetype in the Dictionary.
Note that using a plain List for `g:ale_fixers` is not supported.
```vim
" In ~/.vim/vimrc, or somewhere similar.
let g:ale_fixers = { let g:ale_fixers = {
\ '*': ['remove_trailing_lines', 'trim_whitespace'],
\ 'javascript': ['eslint'], \ 'javascript': ['eslint'],
\} \}
```
If you want to automatically fix files when you save them, you need to turn " Set this setting in vimrc if you want to fix files automatically on save.
a setting on in vimrc. " This is off by default.
```vim
" Set this variable to 1 to fix files when you save them.
let g:ale_fix_on_save = 1 let g:ale_fix_on_save = 1
``` ```
The `:ALEFixSuggest` command will suggest some supported tools for fixing code. The `:ALEFixSuggest` command will suggest some supported tools for fixing code,
Both `g:ale_fixers` and `b:ale_fixers` can also accept functions, including but fixers can be also implemented with functions, including lambda functions
lambda functions, as fixers, for fixing files with custom tools. too. See `:help ale-fix` for detailed information.
See `:help ale-fix` for complete information on how to fix files with ALE.
<a name="usage-completion"></a> <a name="usage-completion"></a>
@@ -161,46 +220,15 @@ See `:help ale-fix` for complete information on how to fix files with ALE.
ALE offers some support for completion via hijacking of omnicompletion while you ALE offers some support for completion via hijacking of omnicompletion while you
type. All of ALE's completion information must come from Language Server type. All of ALE's completion information must come from Language Server
Protocol linters, or from `tsserver` for TypeScript. Protocol linters, or similar protocols. At the moment, completion is only
supported for TypeScript code with `tsserver`, when `tsserver` is enabled. You
ALE integrates with [Deoplete](https://github.com/Shougo/deoplete.nvim) as a can enable completion like so:
completion source, named `'ale'`. You can configure Deoplete to only use ALE as
the source of completion information, or mix it with other sources.
```vim
" Use ALE and also some plugin 'foobar' as completion sources for all code.
call deoplete#custom#option('sources', {
\ '_': ['ale', 'foobar'],
\})
```
ALE also offers its own automatic completion support, which does not require any
other plugins, and can be enabled by changing a setting before ALE is loaded.
```vim ```vim
" Enable completion where available. " Enable completion where available.
" This setting must be set before ALE is loaded.
"
" You should not turn this setting on if you wish to use ALE as a completion
" source for other completion plugins, like Deoplete.
let g:ale_completion_enabled = 1 let g:ale_completion_enabled = 1
``` ```
ALE provides an omni-completion function you can use for triggering
completion manually with `<C-x><C-o>`.
```vim
set omnifunc=ale#completion#OmniFunc
```
When working with TypeScript files, ALE supports automatic imports from
external modules. This behavior is disabled by default and can be enabled by
setting:
```vim
let g:ale_completion_tsserver_autoimport = 1
```
See `:help ale-completion` for more information. See `:help ale-completion` for more information.
<a name="usage-go-to-definition"></a> <a name="usage-go-to-definition"></a>
@@ -208,47 +236,10 @@ See `:help ale-completion` for more information.
### 2.iv Go To Definition ### 2.iv Go To Definition
ALE supports jumping to the definition of words under your cursor with the ALE supports jumping to the definition of words under your cursor with the
`:ALEGoToDefinition` command using any enabled Language Server Protocol linters `:ALEGoToDefinition` command using any enabled LSP linters and `tsserver`.
and `tsserver`.
See `:help ale-go-to-definition` for more information. See `:help ale-go-to-definition` for more information.
<a name="usage-find-references"></a>
### 2.v Find References
ALE supports finding references for words under your cursor with the
`:ALEFindReferences` command using any enabled Language Server Protocol linters
and `tsserver`.
See `:help ale-find-references` for more information.
<a name="usage-hover"></a>
### 2.vi Hovering
ALE supports "hover" information for printing brief information about symbols at
the cursor taken from Language Server Protocol linters and `tsserver` with the
`ALEHover` command.
The information can be displayed in a `balloon` tooltip in Vim or GVim by
hovering your mouse over symbols. Mouse hovering is enabled by default in GVim,
and needs to be configured for Vim 8.1+ in terminals.
See `:help ale-hover` for more information.
<a name="usage-symbol-search"></a>
### 2.vii Symbol Search
ALE supports searching for workspace symbols via Language Server Protocol
linters with the `ALESymbolSearch` command.
Search queries can be performed to find functions, types, and more which are
similar to a given query string.
See `:help ale-symbol-search` for more information.
<a name="installation"></a> <a name="installation"></a>
## 3. Installation ## 3. Installation
@@ -270,14 +261,14 @@ any other tools. Simply clone the plugin into your `pack` directory.
```bash ```bash
mkdir -p ~/.vim/pack/git-plugins/start mkdir -p ~/.vim/pack/git-plugins/start
git clone --depth 1 https://github.com/dense-analysis/ale.git ~/.vim/pack/git-plugins/start/ale git clone https://github.com/w0rp/ale.git ~/.vim/pack/git-plugins/start/ale
``` ```
#### NeoVim on Unix #### NeoVim on Unix
```bash ```bash
mkdir -p ~/.local/share/nvim/site/pack/git-plugins/start mkdir -p ~/.local/share/nvim/site/pack/git-plugins/start
git clone --depth 1 https://github.com/dense-analysis/ale.git ~/.local/share/nvim/site/pack/git-plugins/start/ale git clone https://github.com/w0rp/ale.git ~/.local/share/nvim/site/pack/git-plugins/start/ale
``` ```
#### Vim 8 on Windows #### Vim 8 on Windows
@@ -285,7 +276,7 @@ git clone --depth 1 https://github.com/dense-analysis/ale.git ~/.local/share/nvi
```bash ```bash
# Run these commands in the "Git for Windows" Bash terminal # Run these commands in the "Git for Windows" Bash terminal
mkdir -p ~/vimfiles/pack/git-plugins/start mkdir -p ~/vimfiles/pack/git-plugins/start
git clone --depth 1 https://github.com/dense-analysis/ale.git ~/vimfiles/pack/git-plugins/start/ale git clone https://github.com/w0rp/ale.git ~/vimfiles/pack/git-plugins/start/ale
``` ```
#### Generating Vim help files #### Generating Vim help files
@@ -316,7 +307,7 @@ You can run the following commands in your terminal to do so:
```bash ```bash
cd ~/.vim/bundle cd ~/.vim/bundle
git clone https://github.com/dense-analysis/ale.git git clone https://github.com/w0rp/ale.git
``` ```
<a name="installation-with-vundle"></a> <a name="installation-with-vundle"></a>
@@ -327,36 +318,24 @@ You can install this plugin using [Vundle](https://github.com/VundleVim/Vundle.v
by using the path on GitHub for this repository. by using the path on GitHub for this repository.
```vim ```vim
Plugin 'dense-analysis/ale' Plugin 'w0rp/ale'
``` ```
See the Vundle documentation for more information. See the Vundle documentation for more information.
<a name="installation-with-vim-plug"></a>
### 3.iiii. Installation with Vim-Plug
You can install this plugin using [Vim-Plug](https://github.com/junegunn/vim-plug)
by adding the GitHub path for this repository to your `~/.vimrc`
and running `:PlugInstall`.
```vim
Plug 'dense-analysis/ale'
```
<a name="contributing"></a> <a name="contributing"></a>
## 4. Contributing ## 4. Contributing
If you would like to see support for more languages and tools, please If you would like to see support for more languages and tools, please
[create an issue](https://github.com/dense-analysis/ale/issues) [create an issue](https://github.com/w0rp/ale/issues)
or [create a pull request](https://github.com/dense-analysis/ale/pulls). or [create a pull request](https://github.com/w0rp/ale/pulls).
If your tool can read from stdin or you have code to suggest which is good, If your tool can read from stdin or you have code to suggest which is good,
support can be happily added for it. support can be happily added for it.
If you are interested in the general direction of the project, check out the If you are interested in the general direction of the project, check out the
[wiki home page](https://github.com/dense-analysis/ale/wiki). The wiki includes [wiki home page](https://github.com/w0rp/ale/wiki). The wiki includes a
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 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). on Freenode. Web chat is available [here](https://webchat.freenode.net/?channels=vim-ale).
@@ -369,28 +348,12 @@ on Freenode. Web chat is available [here](https://webchat.freenode.net/?channels
### 5.i. How do I disable particular linters? ### 5.i. How do I disable particular linters?
By default, all available tools for all supported languages will be run. If you By default, all available tools for all supported languages will be run.
want to only select a subset of the tools, you can define `b:ale_linters` for a If you want to only select a subset of the tools, simply create a
single buffer, or `g:ale_linters` globally. `g:ale_linters` dictionary in your vimrc file mapping filetypes
to lists of linters to run.
The recommended way to configure linters is to define a List in an ftplugin
file.
```vim ```vim
" In ~/.vim/ftplugin/javascript.vim, or somewhere similar.
" Enable ESLint only for JavaScript.
let b:ale_linters = ['eslint']
" Equivalent to the above.
let b:ale_linters = {'javascript': ['eslint']}
```
You can also declare which linters you want to run in your vimrc file, before or
after ALE has been loaded.
```vim
" In ~/.vim/vimrc, or somewhere similar.
let g:ale_linters = { let g:ale_linters = {
\ 'javascript': ['eslint'], \ 'javascript': ['eslint'],
\} \}
@@ -401,14 +364,6 @@ be run for those languages, just as when the dictionary is not defined.
Running many linters should not typically obstruct editing in Vim, Running many linters should not typically obstruct editing in Vim,
as they will all be executed in separate processes simultaneously. as they will all be executed in separate processes simultaneously.
If you don't want ALE to run anything other than what you've explicitly asked
for, you can set `g:ale_linters_explicit` to `1`.
```vim
" Only run linters named in ale_linters settings.
let g:ale_linters_explicit = 1
```
This plugin will look for linters in the [`ale_linters`](ale_linters) directory. This plugin will look for linters in the [`ale_linters`](ale_linters) directory.
Each directory within corresponds to a particular filetype in Vim, and each file Each directory within corresponds to a particular filetype in Vim, and each file
in each directory corresponds to the name of a particular linter. in each directory corresponds to the name of a particular linter.
@@ -485,16 +440,8 @@ let g:airline#extensions#ale#enabled = 1
``` ```
If you don't want to use vim-airline, you can implement your own statusline If you don't want to use vim-airline, you can implement your own statusline
function without adding any other plugins. ALE provides some functions to function without adding any other plugins. ALE provides a function for counting
assist in this endeavour, including: the number of problems for this purpose, named `ale#statusline#Count`.
* `ale#statusline#Count`: Which returns the number of problems found by ALE
for a specified buffer.
* `ale#statusline#FirstProblem`: Which returns a dictionary containing the
full loclist details of the first problem of a specified type found by ALE
in a buffer. (e.g. The first style warning in the current buffer.)
This can be useful for displaying more detailed information such as the
line number of the first problem in a file.
Say you want to display all errors as one figure, and all non-errors as another Say you want to display all errors as one figure, and all non-errors as another
figure. You can do the following: figure. You can do the following:
@@ -516,8 +463,7 @@ endfunction
set statusline=%{LinterStatus()} set statusline=%{LinterStatus()}
``` ```
See `:help ale#statusline#Count()` or `:help ale#statusline#FirstProblem()` See `:help ale#statusline#Count()` for more information.
for more information.
<a name="faq-lightline"></a> <a name="faq-lightline"></a>
@@ -536,10 +482,8 @@ 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
* `%...code...%` is an optional error code, and most characters can be
written between the `%` characters.
* `%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.
@@ -553,30 +497,24 @@ let g:ale_echo_msg_format = '[%linter%] %s [%severity%]'
Will give you: Will give you:
![Echoed message](https://user-images.githubusercontent.com/3518142/59195927-348bd000-8b85-11e9-88b6-508a094f1548.png) ![Echoed message](img/echo.png)
See `:help g:ale_echo_msg_format` for more information.
<a name="faq-autocmd"></a> <a name="faq-autocmd"></a>
### 5.viii. How can I execute some code when ALE starts or stops linting? ### 5.viii. How can I execute some code when ALE starts or stops linting?
ALE runs its own [autocmd](http://vimdoc.sourceforge.net/htmldoc/autocmd.html) ALE runs its own [autocmd](http://vimdoc.sourceforge.net/htmldoc/autocmd.html)
events when a lint or fix cycle are started and stopped. There is also an event events when a lint or fix cycle are started and stopped. These events can be
that runs when a linter job has been successfully started. These events can be used to call arbitrary functions before and after ALE stops linting.
used to call arbitrary functions during these respective parts of the ALE's
operation.
```vim ```vim
augroup YourGroup augroup YourGroup
autocmd! autocmd!
autocmd User ALELintPre call YourFunction() autocmd User ALELintPre call YourFunction()
autocmd User ALELintPost call YourFunction() autocmd User ALELintPost call YourFunction()
autocmd User ALEJobStarted call YourFunction() autocmd User ALEFixPre call YourFunction()
autocmd User ALEFixPost call YourFunction()
autocmd User ALEFixPre call YourFunction()
autocmd User ALEFixPost call YourFunction()
augroup END augroup END
``` ```
@@ -608,7 +546,6 @@ options off.
```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_text_changed = 'never'
let g:ale_lint_on_insert_leave = 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
@@ -668,20 +605,11 @@ augroup END
``` ```
Supposing the filetype has been set correctly, you can set the following Supposing the filetype has been set correctly, you can set the following
options in a jsx.vim ftplugin file. options in your vimrc file:
```vim ```vim
" In ~/.vim/ftplugin/jsx.vim, or somewhere similar.
let b:ale_linter_aliases = ['css', 'javascript']
let b:ale_linters = ['stylelint', 'eslint']
```
Or if you want, you can configure the linters from your vimrc file.
```vim
" In ~/.vim/vimrc, or somewhere similar.
let g:ale_linter_aliases = {'jsx': ['css', 'javascript']}
let g:ale_linters = {'jsx': ['stylelint', 'eslint']} let g:ale_linters = {'jsx': ['stylelint', 'eslint']}
let g:ale_linter_aliases = {'jsx': 'css'}
``` ```
ALE will alias the `jsx` filetype so it uses the `css` filetype linters, and ALE will alias the `jsx` filetype so it uses the `css` filetype linters, and
@@ -689,40 +617,9 @@ use the original Array of selected linters for `jsx` from the `g:ale_linters`
object. All available linters will be used for the filetype `javascript`, and object. All available linters will be used for the filetype `javascript`, and
no linter will be run twice for the same file. no linter will be run twice for the same file.
<a name="faq-vue-eslint"></a>
### 5.xiii. How can I check Vue files with ESLint?
To check Vue files with ESLint, your ESLint project configuration file must be
configured to use the [Vue plugin](https://github.com/vuejs/eslint-plugin-vue).
After that, you need to configure ALE so it will run the JavaScript ESLint
linter on your files. The settings you need are similar to the settings needed
for checking JSX code with both stylelint and ESLint, in the previous section.
```vim
" In ~/.vim/ftplugin/vue.vim, or somewhere similar.
" Run both javascript and vue linters for vue files.
let b:ale_linter_aliases = ['javascript', 'vue']
" Select the eslint and vls linters.
let b:ale_linters = ['eslint', 'vls']
```
Run `:ALEInfo` to see which linters are available after telling ALE to run
JavaScript linters on Vue files. Not all linters support checking Vue files.
If you don't want to configure your linters in ftplugin files for some reason,
you can configure them from your vimrc file instead.
```vim
" In ~/.vim/vimrc, or somewhere similar.
let g:ale_linter_aliases = {'vue': ['vue', 'javascript']}
let g:ale_linters = {'vue': ['eslint', 'vls']}
```
<a name="faq-my-battery-is-sad"></a> <a name="faq-my-battery-is-sad"></a>
### 5.xiv. Will this plugin eat all of my laptop battery power? ### 5.xiii. Will this plugin eat all of my laptop battery power?
ALE takes advantage of the power of various tools to check your code. This of ALE takes advantage of the power of various tools to check your code. This of
course means that CPU time will be used to continuously check your code. If you course means that CPU time will be used to continuously check your code. If you
@@ -735,10 +632,11 @@ while you type. ALE uses a timeout which is cancelled and reset every time you
type, and this delay can be increased so linters are run less often. See 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 behaviour. If you don't wish to run linters while you type, you can disable that
Set `g:ale_lint_on_text_changed` to `never`. You won't get as frequent error behaviour. Set `g:ale_lint_on_text_changed` to `never` or `normal`. You won't
checking, but ALE shouldn't block your ability to edit a document after you save get as frequent error checking, but ALE shouldn't block your ability to edit a
a file, so the asynchronous nature of the plugin will still be an advantage. document after you save a file, so the asynchronous nature of the plugin will
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
@@ -746,7 +644,7 @@ including the option `g:ale_lint_on_enter`, and you can run ALE manually with
<a name="faq-c-configuration"></a> <a name="faq-c-configuration"></a>
### 5.xv. How can I configure my C or C++ project? ### 5.xiv. How can I configure my C or C++ project?
The structure of C and C++ projects varies wildly from project to project, with The structure of C and C++ projects varies wildly from project to project, with
many different build tools being used for building them, and many different many different build tools being used for building them, and many different
@@ -755,9 +653,8 @@ ALE cannot easily detect which compiler flags to use.
Some tools and build configurations can generate Some tools and build configurations can generate
[compile_commands.json](https://clang.llvm.org/docs/JSONCompilationDatabase.html) [compile_commands.json](https://clang.llvm.org/docs/JSONCompilationDatabase.html)
files. The `cppcheck`, `clangcheck`, `clangtidy` and `cquery` linters can read files. The `cppcheck`, `clangcheck` and `clangtidy` linters can read these
these files for automatically determining the appropriate compiler flags to files for automatically determining the appropriate compiler flags to use.
use.
For linting with compilers like `gcc` and `clang`, and with other tools, you For linting with compilers like `gcc` and `clang`, and with other tools, you
will need to tell ALE which compiler flags to use yourself. You can use will need to tell ALE which compiler flags to use yourself. You can use
@@ -772,7 +669,7 @@ used for executing local vimrc files which can be shared in your project.
<a name="faq-buffer-configuration"></a> <a name="faq-buffer-configuration"></a>
### 5.xvi. How can I configure ALE differently for different buffers? ### 5.xv. How can I configure ALE differently for different buffers?
ALE offers various ways to configure which linters or fixers are run, and ALE offers various ways to configure which linters or fixers are run, and
other settings. For the majority of ALE's settings, they can either be other settings. For the majority of ALE's settings, they can either be
@@ -808,7 +705,7 @@ Buffer-local variables for settings always override the global settings.
<a name="faq-list-window-height"></a> <a name="faq-list-window-height"></a>
### 5.xvii. How can I configure the height of the list in which ALE displays errors? ### 5.xvi. How can I configure the height of the list in which ALE displays errors?
To set a default height for the error list, use the `g:ale_list_window_size` variable. To set a default height for the error list, use the `g:ale_list_window_size` variable.
@@ -816,13 +713,3 @@ To set a default height for the error list, use the `g:ale_list_window_size` var
" Show 5 lines of errors (default: 10) " Show 5 lines of errors (default: 10)
let g:ale_list_window_size = 5 let g:ale_list_window_size = 5
``` ```
<a name="faq-get-info"></a>
### 5.xviii. How can I see what ALE has configured for the current file?
Run the following to see what is currently configured:
```vim
:ALEInfo
```

37
after/plugin/ale.vim Normal file
View File

@@ -0,0 +1,37 @@
" Author: w0rp <devw0rp@gmail.com>
" Description: Follow-up checks for the plugin: warn about conflicting plugins.
" A flag for ensuring that this is not run more than one time.
if exists('g:loaded_ale_after')
finish
endif
" Set the flag so this file is not run more than one time.
let g:loaded_ale_after = 1
" Check if the flag is available and set to 0 to disable checking for and
" emitting conflicting plugin warnings.
if exists('g:ale_emit_conflict_warnings') && !g:ale_emit_conflict_warnings
finish
endif
" Conflicting Plugins Checks
function! s:GetConflictingPluginWarning(plugin_name) abort
return 'ALE conflicts with ' . a:plugin_name
\ . '. Uninstall it, or disable this warning with '
\ . '`let g:ale_emit_conflict_warnings = 0` in your vimrc file, '
\ . '*before* plugins are loaded.'
endfunction
if exists('g:loaded_syntastic_plugin')
throw s:GetConflictingPluginWarning('Syntastic')
endif
if exists('g:loaded_neomake')
throw s:GetConflictingPluginWarning('Neomake')
endif
if exists('g:loaded_validator_plugin')
throw s:GetConflictingPluginWarning('Validator')
endif

View File

@@ -1,54 +0,0 @@
" Author: Martino Pilia <martino.pilia@gmail.com>
" Description: Lint Ada files with GCC
call ale#Set('ada_gcc_executable', 'gcc')
" -gnatwa: activate most optional warnings
" -gnatq: try semantic analysis even if syntax errors have been found
call ale#Set('ada_gcc_options', '-gnatwa -gnatq')
function! ale_linters#ada#gcc#GetCommand(buffer) abort
" Build a suitable output file name. The output file is specified because
" the .ali file may be created even if no code generation is attempted.
" The output file name must match the source file name (except for the
" extension), so here we cannot use the null file as output.
let l:tmp_dir = fnamemodify(ale#command#CreateDirectory(a:buffer), ':p')
let l:out_file = l:tmp_dir . fnamemodify(bufname(a:buffer), ':t:r') . '.o'
" -gnatc: Check syntax and semantics only (no code generation attempted)
return '%e -x ada -c -gnatc'
\ . ' -o ' . ale#Escape(l:out_file)
\ . ' -I ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ale#Pad(ale#Var(a:buffer, 'ada_gcc_options'))
\ . ' %t'
endfunction
" For the message format please refer to:
" https://gcc.gnu.org/onlinedocs/gnat_ugn/Output-and-Error-Message-Control.html
" https://gcc.gnu.org/onlinedocs/gnat_ugn/Warning-Message-Control.html
function! ale_linters#ada#gcc#Handle(buffer, lines) abort
" Error format: <filename>:<lnum>:<col>: <text>
" Warning format: <filename>:<lnum>:<col>: warning: <text>
let l:re = '\v(.+):([0-9]+):([0-9]+):\s+(warning:)?\s*(.+)\s*'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:re)
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': str2nr(l:match[2]),
\ 'col': str2nr(l:match[3]),
\ 'type': l:match[4] is# 'warning:' ? 'W' : 'E',
\ 'text': l:match[5],
\})
endfor
return l:output
endfunction
call ale#linter#Define('ada', {
\ 'name': 'gcc',
\ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'ada_gcc_executable')},
\ 'command': function('ale_linters#ada#gcc#GetCommand'),
\ 'callback': 'ale_linters#ada#gcc#Handle',
\})

View File

@@ -1,12 +1,6 @@
" Author: Bjorn Neergaard <bjorn@neersighted.com> " Author: Bjorn Neergaard <bjorn@neersighted.com>
" Description: ansible-lint for ansible-yaml files " Description: ansible-lint for ansible-yaml files
call ale#Set('ansible_ansible_lint_executable', 'ansible-lint')
function! ale_linters#ansible#ansible_lint#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'ansible_ansible_lint_executable')
endfunction
function! ale_linters#ansible#ansible_lint#Handle(buffer, lines) abort function! ale_linters#ansible#ansible_lint#Handle(buffer, lines) abort
for l:line in a:lines[:10] for l:line in a:lines[:10]
if match(l:line, '^Traceback') >= 0 if match(l:line, '^Traceback') >= 0
@@ -48,9 +42,8 @@ function! ale_linters#ansible#ansible_lint#Handle(buffer, lines) abort
endfunction endfunction
call ale#linter#Define('ansible', { call ale#linter#Define('ansible', {
\ 'name': 'ansible_lint', \ 'name': 'ansible',
\ 'aliases': ['ansible', 'ansible-lint'], \ 'executable': 'ansible',
\ 'executable': function('ale_linters#ansible#ansible_lint#GetExecutable'), \ 'command': 'ansible-lint -p %t',
\ 'command': '%e -p %t',
\ 'callback': 'ale_linters#ansible#ansible_lint#Handle', \ 'callback': 'ale_linters#ansible#ansible_lint#Handle',
\}) \})

View File

@@ -16,12 +16,10 @@ function! ale_linters#apiblueprint#drafter#HandleErrors(buffer, lines) abort
\ 'lnum': l:match[3] + 0, \ 'lnum': l:match[3] + 0,
\ 'col': l:match[4] + 0, \ 'col': l:match[4] + 0,
\} \}
if l:match[5] isnot# '' if l:match[5] isnot# ''
let l:item.end_lnum = l:match[6] + 0 let l:item.end_lnum = l:match[6] + 0
let l:item.end_col = l:match[7] + 0 let l:item.end_col = l:match[7] + 0
endif endif
call add(l:output, l:item) call add(l:output, l:item)
endfor endfor
@@ -33,6 +31,6 @@ call ale#linter#Define('apiblueprint', {
\ 'name': 'drafter', \ 'name': 'drafter',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'drafter', \ 'executable': 'drafter',
\ 'command': 'drafter --use-line-num --validate', \ 'command': 'drafter --use-line-num --validate %t',
\ 'callback': 'ale_linters#apiblueprint#drafter#HandleErrors', \ 'callback': 'ale_linters#apiblueprint#drafter#HandleErrors',
\}) \})

View File

@@ -1,4 +1,11 @@
" Author: Johannes Wienke <languitar@semipol.de> " Author: Johannes Wienke <languitar@semipol.de>
" Description: alex for asciidoc files " Description: alex for asciidoc files
call ale#handlers#alex#DefineLinter('asciidoc', '--text') call ale#linter#Define('help', {
\ 'name': 'alex',
\ 'executable': 'alex',
\ 'command': 'alex %s -t',
\ 'output_stream': 'stderr',
\ 'callback': 'ale#handlers#alex#Handle',
\ 'lint_file': 1,
\})

View File

@@ -1,9 +0,0 @@
" Author: TANIGUCHI Masaya <ta2gch@gmail.com>
" Description: textlint for AsciiDoc files
call ale#linter#Define('asciidoc', {
\ 'name': 'textlint',
\ 'executable': function('ale#handlers#textlint#GetExecutable'),
\ 'command': function('ale#handlers#textlint#GetCommand'),
\ 'callback': 'ale#handlers#textlint#HandleTextlintOutput',
\})

View File

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

View File

@@ -0,0 +1,9 @@
" Author: Sumner Evans <sumner.evans98@gmail.com>
" Description: write-good for AsciiDoc files
call ale#linter#Define('asciidoc', {
\ 'name': 'write-good',
\ 'executable_callback': 'ale#handlers#writegood#GetExecutable',
\ 'command_callback': 'ale#handlers#writegood#GetCommand',
\ 'callback': 'ale#handlers#writegood#Handle',
\})

View File

@@ -1,4 +0,0 @@
" Author: Sumner Evans <sumner.evans98@gmail.com>
" Description: write-good for AsciiDoc files
call ale#handlers#writegood#DefineLinter('asciidoc')

View File

@@ -4,13 +4,15 @@
call ale#Set('asm_gcc_executable', 'gcc') call ale#Set('asm_gcc_executable', 'gcc')
call ale#Set('asm_gcc_options', '-Wall') call ale#Set('asm_gcc_options', '-Wall')
function! ale_linters#asm#gcc#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'asm_gcc_executable')
endfunction
function! ale_linters#asm#gcc#GetCommand(buffer) abort function! ale_linters#asm#gcc#GetCommand(buffer) abort
" `-o /dev/null` or `-o null` is needed to catch all errors, return ale#Escape(ale_linters#asm#gcc#GetExecutable(a:buffer))
" -fsyntax-only doesn't catch everything. \ . ' -x assembler -fsyntax-only '
return '%e -x assembler' \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ' -o ' . g:ale#util#nul_file \ . ' ' . ale#Var(a:buffer, 'asm_gcc_options') . ' -'
\ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ' ' . ale#Var(a:buffer, 'asm_gcc_options') . ' -'
endfunction endfunction
function! ale_linters#asm#gcc#Handle(buffer, lines) abort function! ale_linters#asm#gcc#Handle(buffer, lines) abort
@@ -31,7 +33,7 @@ endfunction
call ale#linter#Define('asm', { call ale#linter#Define('asm', {
\ 'name': 'gcc', \ 'name': 'gcc',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'asm_gcc_executable')}, \ 'executable_callback': 'ale_linters#asm#gcc#GetExecutable',
\ 'command': function('ale_linters#asm#gcc#GetCommand'), \ 'command_callback': 'ale_linters#asm#gcc#GetCommand',
\ 'callback': 'ale_linters#asm#gcc#Handle', \ 'callback': 'ale_linters#asm#gcc#Handle',
\}) \})

View File

@@ -1,22 +1,30 @@
" Author: kmarc <korondi.mark@gmail.com> " Author: kmarc <korondi.mark@gmail.com>
" Description: This file adds support for using GNU awk with sripts. " Description: This file adds support for using GNU awk with sripts.
call ale#Set('awk_gawk_executable', 'gawk') let g:ale_awk_gawk_executable =
call ale#Set('awk_gawk_options', '') \ 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 function! ale_linters#awk#gawk#GetCommand(buffer) abort
" note the --source 'BEGIN ...' is to prevent " note the --source 'BEGIN ...' is to prevent
" gawk from attempting to execute the body of the script " gawk from attempting to execute the body of the script
" it is linting. " it is linting.
return '%e --source ' . ale#Escape('BEGIN { exit } END { exit 1 }') return ale_linters#awk#gawk#GetExecutable(a:buffer)
\ . ale#Pad(ale#Var(a:buffer, 'awk_gawk_options')) \ . " --source 'BEGIN { exit } END { exit 1 }'"
\ . ' -f %t --lint /dev/null' \ . ' ' . ale#Var(a:buffer, 'awk_gawk_options')
\ . ' ' . '-f %t --lint /dev/null'
endfunction endfunction
call ale#linter#Define('awk', { call ale#linter#Define('awk', {
\ 'name': 'gawk', \ 'name': 'gawk',
\ 'executable': {b -> ale#Var(b, 'awk_gawk_executable')}, \ 'executable_callback': 'ale_linters#awk#gawk#GetExecutable',
\ 'command': function('ale_linters#awk#gawk#GetCommand'), \ 'command_callback': 'ale_linters#awk#gawk#GetCommand',
\ 'callback': 'ale#handlers#gawk#HandleGawkFormat', \ 'callback': 'ale#handlers#gawk#HandleGawkFormat',
\ 'output_stream': 'both' \ 'output_stream': 'both'
\}) \})

View File

@@ -1,4 +0,0 @@
" Author: Ian2020 <https://github.com/Ian2020>
" Description: shellcheck linter for bats scripts.
call ale#handlers#shellcheck#DefineLinter('bats')

View File

@@ -1,75 +0,0 @@
" Author: Horacio Sanson - https://github.com/hsanson
" Description: Support for bibclean linter for BibTeX files.
call ale#Set('bib_bibclean_executable', 'bibclean')
function! ale_linters#bib#bibclean#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'bib_bibclean_executable')
return ale#Escape(l:executable) . ' -file-position '
endfunction
function! ale_linters#bib#bibclean#get_type(str) abort
if a:str is# '??'
return 'E'
else
return 'W'
endif
endfunction
function! ale_linters#bib#bibclean#match_msg(line) abort
return matchlist(a:line, '^\(.*\) "stdin", line \(.*\): \(.*\)$')
endfunction
function! ale_linters#bib#bibclean#match_entry(line) abort
return matchlist(a:line, 'Entry input byte=.* line=\(.*\) column=\(.*\) output .*$')
endfunction
function! ale_linters#bib#bibclean#match_value(line) abort
return matchlist(a:line, 'Value input byte=.* line=\(.*\) column=\(.*\) output .*$')
endfunction
function! ale_linters#bib#bibclean#Handle(buffer, lines) abort
let l:output = []
let l:type = 'E'
let l:msg = ''
for l:line in a:lines
if empty(l:msg)
let l:mlist = ale_linters#bib#bibclean#match_msg(l:line)
if !empty(l:mlist)
let l:msg = l:mlist[3]
let l:type = ale_linters#bib#bibclean#get_type(l:mlist[1])
endif
else
if l:type is# 'E'
let l:mlist = ale_linters#bib#bibclean#match_entry(l:line)
else
let l:mlist = ale_linters#bib#bibclean#match_value(l:line)
endif
if !empty(l:mlist)
call add(l:output, {
\ 'lnum': l:mlist[1],
\ 'col': l:mlist[2],
\ 'text': l:msg,
\ 'type': l:type
\})
let l:msg = ''
endif
endif
endfor
return l:output
endfunction
call ale#linter#Define('bib', {
\ 'name': 'bibclean',
\ 'executable': {b -> ale#Var(b, 'bib_bibclean_executable')},
\ 'command': function('ale_linters#bib#bibclean#GetCommand'),
\ 'output_stream': 'stderr',
\ 'callback': 'ale_linters#bib#bibclean#Handle',
\})

View File

@@ -1,14 +0,0 @@
" Author: Ye Jingchen <ye.jingchen@gmail.com>, Ben Falconer <ben@falconers.me.uk>, jtalowell <jtalowell@protonmail.com>
" Description: A language server for C
call ale#Set('c_ccls_executable', 'ccls')
call ale#Set('c_ccls_init_options', {})
call ale#linter#Define('c', {
\ 'name': 'ccls',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'c_ccls_executable')},
\ 'command': '%e',
\ 'project_root': function('ale#handlers#ccls#GetProjectRoot'),
\ 'initialization_options': {b -> ale#Var(b, 'c_ccls_init_options')},
\})

View File

@@ -4,21 +4,26 @@
call ale#Set('c_clang_executable', 'clang') call ale#Set('c_clang_executable', 'clang')
call ale#Set('c_clang_options', '-std=c11 -Wall') call ale#Set('c_clang_options', '-std=c11 -Wall')
function! ale_linters#c#clang#GetCommand(buffer, output) abort function! ale_linters#c#clang#GetExecutable(buffer) abort
let l:cflags = ale#c#GetCFlags(a:buffer, a:output) return ale#Var(a:buffer, 'c_clang_executable')
endfunction
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 '%e -S -x c -fsyntax-only' return ale#Escape(ale_linters#c#clang#GetExecutable(a:buffer))
\ . ' -iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) \ . ' -S -x c -fsyntax-only '
\ . ale#Pad(l:cflags) \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' '
\ . ale#Pad(ale#Var(a:buffer, 'c_clang_options')) . ' -' \ . ale#c#IncludeOptions(l:paths)
\ . ale#Var(a:buffer, 'c_clang_options') . ' -'
endfunction endfunction
call ale#linter#Define('c', { call ale#linter#Define('c', {
\ 'name': 'clang', \ 'name': 'clang',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'c_clang_executable')}, \ 'executable_callback': 'ale_linters#c#clang#GetExecutable',
\ 'command': {b -> ale#c#RunMakeCommand(b, function('ale_linters#c#clang#GetCommand'))}, \ 'command_callback': 'ale_linters#c#clang#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\}) \})

View File

@@ -1,22 +0,0 @@
" Author: Andrey Melentyev <andrey.melentyev@protonmail.com>
" Description: Clangd language server
call ale#Set('c_clangd_executable', 'clangd')
call ale#Set('c_clangd_options', '')
call ale#Set('c_build_dir', '')
function! ale_linters#c#clangd#GetCommand(buffer) abort
let l:build_dir = ale#c#GetBuildDirectory(a:buffer)
return '%e'
\ . ale#Pad(ale#Var(a:buffer, 'c_clangd_options'))
\ . (!empty(l:build_dir) ? ' -compile-commands-dir=' . ale#Escape(l:build_dir) : '')
endfunction
call ale#linter#Define('c', {
\ 'name': 'clangd',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'c_clangd_executable')},
\ 'command': function('ale_linters#c#clangd#GetCommand'),
\ 'project_root': function('ale#c#FindProjectRoot'),
\})

View File

@@ -10,33 +10,45 @@ call ale#Set('c_clangtidy_executable', 'clang-tidy')
" Consult the check list in clang-tidy's documentation: " Consult the check list in clang-tidy's documentation:
" http://clang.llvm.org/extra/clang-tidy/checks/list.html " http://clang.llvm.org/extra/clang-tidy/checks/list.html
call ale#Set('c_clangtidy_checks', []) call ale#Set('c_clangtidy_checks', ['*'])
" Set this option to manually set some options for clang-tidy to use as compile " Set this option to manually set some options for clang-tidy.
" flags.
" This will disable compile_commands.json detection. " This will disable compile_commands.json detection.
call ale#Set('c_clangtidy_options', '') call ale#Set('c_clangtidy_options', '')
" Set this option to manually set options for clang-tidy directly.
call ale#Set('c_clangtidy_extra_options', '')
call ale#Set('c_build_dir', '') call ale#Set('c_build_dir', '')
function! ale_linters#c#clangtidy#GetCommand(buffer, output) abort function! ale_linters#c#clangtidy#GetExecutable(buffer) abort
let l:checks = join(ale#Var(a:buffer, 'c_clangtidy_checks'), ',') return ale#Var(a:buffer, 'c_clangtidy_executable')
let l:build_dir = ale#c#GetBuildDirectory(a:buffer) endfunction
let l:options = ''
" Get the extra options if we couldn't find a build directory. function! s:GetBuildDirectory(buffer) abort
if empty(l:build_dir) " Don't include build directory for header files, as compile_commands.json
let l:options = ale#Var(a:buffer, 'c_clangtidy_options') " files don't consider headers to be translation units, and provide no
let l:cflags = ale#c#GetCFlags(a:buffer, a:output) " commands for compiling header files.
let l:options .= !empty(l:options) ? ale#Pad(l:cflags) : l:cflags if expand('#' . a:buffer) =~# '\v\.(h|hpp)$'
return ''
endif endif
" Get the options to pass directly to clang-tidy let l:build_dir = ale#Var(a:buffer, 'c_build_dir')
let l:extra_options = ale#Var(a:buffer, 'c_clangtidy_extra_options')
return '%e' " 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#c#clangtidy#GetCommand(buffer) abort
let l:checks = join(ale#Var(a:buffer, 'c_clangtidy_checks'), ',')
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, 'c_clangtidy_options')
\ : ''
return ale#Escape(ale_linters#c#clangtidy#GetExecutable(a:buffer))
\ . (!empty(l:checks) ? ' -checks=' . ale#Escape(l:checks) : '') \ . (!empty(l:checks) ? ' -checks=' . ale#Escape(l:checks) : '')
\ . (!empty(l:extra_options) ? ' ' . ale#Escape(l:extra_options) : '')
\ . ' %s' \ . ' %s'
\ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '') \ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '')
\ . (!empty(l:options) ? ' -- ' . l:options : '') \ . (!empty(l:options) ? ' -- ' . l:options : '')
@@ -45,8 +57,8 @@ endfunction
call ale#linter#Define('c', { call ale#linter#Define('c', {
\ 'name': 'clangtidy', \ 'name': 'clangtidy',
\ 'output_stream': 'stdout', \ 'output_stream': 'stdout',
\ 'executable': {b -> ale#Var(b, 'c_clangtidy_executable')}, \ 'executable_callback': 'ale_linters#c#clangtidy#GetExecutable',
\ 'command': {b -> ale#c#RunMakeCommand(b, function('ale_linters#c#clangtidy#GetCommand'))}, \ 'command_callback': 'ale_linters#c#clangtidy#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\ 'lint_file': 1, \ 'lint_file': 1,
\}) \})

View File

@@ -4,25 +4,36 @@
call ale#Set('c_cppcheck_executable', 'cppcheck') call ale#Set('c_cppcheck_executable', 'cppcheck')
call ale#Set('c_cppcheck_options', '--enable=style') call ale#Set('c_cppcheck_options', '--enable=style')
function! ale_linters#c#cppcheck#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'c_cppcheck_executable')
endfunction
function! ale_linters#c#cppcheck#GetCommand(buffer) abort function! ale_linters#c#cppcheck#GetCommand(buffer) abort
let l:cd_command = ale#handlers#cppcheck#GetCdCommand(a:buffer) " Search upwards from the file for compile_commands.json.
let l:compile_commands_option = ale#handlers#cppcheck#GetCompileCommandsOptions(a:buffer) "
let l:buffer_path_include = empty(l:compile_commands_option) " If we find it, we'll `cd` to where the compile_commands.json file is,
\ ? ale#handlers#cppcheck#GetBufferPathIncludeOptions(a:buffer) " 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 return l:cd_command
\ . '%e -q --language=c' \ . ale#Escape(ale_linters#c#cppcheck#GetExecutable(a:buffer))
\ . ale#Pad(l:compile_commands_option) \ . ' -q --language=c '
\ . ale#Pad(ale#Var(a:buffer, 'c_cppcheck_options')) \ . l:compile_commands_option
\ . l:buffer_path_include \ . ale#Var(a:buffer, 'c_cppcheck_options')
\ . ' %t' \ . ' %t'
endfunction endfunction
call ale#linter#Define('c', { call ale#linter#Define('c', {
\ 'name': 'cppcheck', \ 'name': 'cppcheck',
\ 'output_stream': 'both', \ 'output_stream': 'both',
\ 'executable': {b -> ale#Var(b, 'c_cppcheck_executable')}, \ 'executable_callback': 'ale_linters#c#cppcheck#GetExecutable',
\ 'command': function('ale_linters#c#cppcheck#GetCommand'), \ 'command_callback': 'ale_linters#c#cppcheck#GetCommand',
\ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat', \ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat',
\}) \})

View File

@@ -1,30 +0,0 @@
" Author: Ben Falconer <ben@falconers.me.uk>, jtalowell <jtalowell@protonmail.com>
" Description: A language server for C
call ale#Set('c_cquery_executable', 'cquery')
call ale#Set('c_cquery_cache_directory', expand('~/.cache/cquery'))
function! ale_linters#c#cquery#GetProjectRoot(buffer) abort
" Try to find cquery configuration files first.
let l:config = ale#path#FindNearestFile(a:buffer, '.cquery')
if !empty(l:config)
return fnamemodify(l:config, ':h')
endif
" Fall back on default project root detection.
return ale#c#FindProjectRoot(a:buffer)
endfunction
function! ale_linters#c#cquery#GetInitializationOptions(buffer) abort
return {'cacheDirectory': ale#Var(a:buffer, 'c_cquery_cache_directory')}
endfunction
call ale#linter#Define('c', {
\ 'name': 'cquery',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'c_cquery_executable')},
\ 'command': '%e',
\ 'project_root': function('ale_linters#c#cquery#GetProjectRoot'),
\ 'initialization_options': function('ale_linters#c#cquery#GetInitializationOptions'),
\})

View File

@@ -6,20 +6,26 @@ call ale#Set('c_flawfinder_options', '')
call ale#Set('c_flawfinder_minlevel', 1) call ale#Set('c_flawfinder_minlevel', 1)
call ale#Set('c_flawfinder_error_severity', 6) call ale#Set('c_flawfinder_error_severity', 6)
function! ale_linters#c#flawfinder#GetCommand(buffer) abort function! ale_linters#c#flawfinder#GetExecutable(buffer) abort
" Set the minimum vulnerability level for flawfinder to bother with return ale#Var(a:buffer, 'c_flawfinder_executable')
let l:minlevel = ' --minlevel=' . ale#Var(a:buffer, 'c_flawfinder_minlevel') endfunction
return '%e -CDQS' function! ale_linters#c#flawfinder#GetCommand(buffer) abort
\ . ale#Pad(ale#Var(a:buffer, 'c_flawfinder_options'))
\ . l:minlevel " Set the minimum vulnerability level for flawfinder to bother with
\ . ' %t' let l:minlevel = ' --minlevel=' . ale#Var(a:buffer, 'c_flawfinder_minlevel')
return ale#Escape(ale_linters#c#flawfinder#GetExecutable(a:buffer))
\ . ' -CDQS'
\ . ale#Var(a:buffer, 'c_flawfinder_options')
\ . l:minlevel
\ . ' %t'
endfunction endfunction
call ale#linter#Define('c', { call ale#linter#Define('c', {
\ 'name': 'flawfinder', \ 'name': 'flawfinder',
\ 'output_stream': 'stdout', \ 'output_stream': 'stdout',
\ 'executable': {b -> ale#Var(b, 'c_flawfinder_executable')}, \ 'executable_callback': 'ale_linters#c#flawfinder#GetExecutable',
\ 'command': function('ale_linters#c#flawfinder#GetCommand'), \ 'command_callback': 'ale_linters#c#flawfinder#GetCommand',
\ 'callback': 'ale#handlers#flawfinder#HandleFlawfinderFormat', \ 'callback': 'ale#handlers#flawfinder#HandleFlawfinderFormat',
\}) \})

View File

@@ -4,25 +4,26 @@
call ale#Set('c_gcc_executable', 'gcc') call ale#Set('c_gcc_executable', 'gcc')
call ale#Set('c_gcc_options', '-std=c11 -Wall') call ale#Set('c_gcc_options', '-std=c11 -Wall')
function! ale_linters#c#gcc#GetCommand(buffer, output) abort function! ale_linters#c#gcc#GetExecutable(buffer) abort
let l:cflags = ale#c#GetCFlags(a:buffer, a:output) return ale#Var(a:buffer, 'c_gcc_executable')
endfunction
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))
" `-o /dev/null` or `-o null` is needed to catch all errors, \ . ' -S -x c -fsyntax-only '
" -fsyntax-only doesn't catch everything. \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' '
return '%e -S -x c' \ . ale#c#IncludeOptions(l:paths)
\ . ' -o ' . g:ale#util#nul_file \ . ale#Var(a:buffer, 'c_gcc_options') . ' -'
\ . ' -iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ale#Pad(l:cflags)
\ . ale#Pad(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': {b -> ale#Var(b, 'c_gcc_executable')}, \ 'executable_callback': 'ale_linters#c#gcc#GetExecutable',
\ 'command': {b -> ale#c#RunMakeCommand(b, function('ale_linters#c#gcc#GetCommand'))}, \ 'command_callback': 'ale_linters#c#gcc#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\}) \})

View File

@@ -1,54 +0,0 @@
" Author: Raphael Hoegger - https://github.com/pfuender
" Description: Cookstyle (RuboCop based), a code style analyzer for Ruby files
call ale#Set('chef_cookstyle_executable', 'cookstyle')
call ale#Set('chef_cookstyle_options', '')
function! ale_linters#chef#cookstyle#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'chef_cookstyle_options')
return '%e' . ale#Pad(escape(l:options, '~')) . ' --force-exclusion --format json --stdin ' . ' %s'
endfunction
function! ale_linters#chef#cookstyle#Handle(buffer, lines) abort
if len(a:lines) == 0
return []
endif
let l:errors = ale#util#FuzzyJSONDecode(a:lines[0], {})
if !has_key(l:errors, 'summary')
\|| l:errors['summary']['offense_count'] == 0
\|| empty(l:errors['files'])
return []
endif
let l:output = []
for l:error in l:errors['files'][0]['offenses']
let l:start_col = str2nr(l:error['location']['start_column'])
let l:end_col = str2nr(l:error['location']['last_column'])
if !l:end_col
let l:end_col = l:start_col + 1
endif
call add(l:output, {
\ 'lnum': str2nr(l:error['location']['line']),
\ 'col': l:start_col,
\ 'end_col': l:end_col,
\ 'code': l:error['cop_name'],
\ 'text': l:error['message'],
\ 'type': l:error['severity'] is? 'convention' ? 'W' : 'E',
\})
endfor
return l:output
endfunction
call ale#linter#Define('chef', {
\ 'name': 'cookstyle',
\ 'executable': {b -> ale#Var(b, 'chef_cookstyle_executable')},
\ 'command': function('ale_linters#chef#cookstyle#GetCommand'),
\ 'callback': 'ale_linters#chef#cookstyle#Handle',
\})

View File

@@ -6,10 +6,17 @@
call ale#Set('chef_foodcritic_executable', 'foodcritic') call ale#Set('chef_foodcritic_executable', 'foodcritic')
call ale#Set('chef_foodcritic_options', '') call ale#Set('chef_foodcritic_options', '')
function! ale_linters#chef#foodcritic#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'chef_foodcritic_executable')
endfunction
function! ale_linters#chef#foodcritic#GetCommand(buffer) abort function! ale_linters#chef#foodcritic#GetCommand(buffer) abort
let l:executable = ale_linters#chef#foodcritic#GetExecutable(a:buffer)
let l:options = ale#Var(a:buffer, 'chef_foodcritic_options') let l:options = ale#Var(a:buffer, 'chef_foodcritic_options')
return '%e' . ale#Pad(escape(l:options, '~')) . ' %s' return ale#Escape(l:executable)
\ . (!empty(l:options) ? ' ' . escape(l:options, '~') : '')
\ . ' %s'
endfunction endfunction
function! ale_linters#chef#foodcritic#Handle(buffer, lines) abort function! ale_linters#chef#foodcritic#Handle(buffer, lines) abort
@@ -34,8 +41,8 @@ endfunction
call ale#linter#Define('chef', { call ale#linter#Define('chef', {
\ 'name': 'foodcritic', \ 'name': 'foodcritic',
\ 'executable': {b -> ale#Var(b, 'chef_foodcritic_executable')}, \ 'executable_callback': 'ale_linters#chef#foodcritic#GetExecutable',
\ 'command': function('ale_linters#chef#foodcritic#GetCommand'), \ 'command_callback': 'ale_linters#chef#foodcritic#GetCommand',
\ 'callback': 'ale_linters#chef#foodcritic#Handle', \ 'callback': 'ale_linters#chef#foodcritic#Handle',
\ 'lint_file': 1, \ 'lint_file': 1,
\}) \})

View File

@@ -1,34 +0,0 @@
" Author: Masashi Iizuka <liquidz.uo@gmail.com>
" Description: linter for clojure using clj-kondo https://github.com/borkdude/clj-kondo
function! ale_linters#clojure#clj_kondo#HandleCljKondoFormat(buffer, lines) abort
" output format
" <filename>:<line>:<column>: <issue type>: <message>
let l:pattern = '\v^[a-zA-Z]?:?[^:]+:(\d+):(\d+):? ((Exception|error|warning): ?(.+))$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:type = 'E'
if l:match[4] is? 'warning'
let l:type = 'W'
endif
call add(l:output, {
\ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0,
\ 'text': l:match[3],
\ 'type': l:type,
\})
endfor
return l:output
endfunction
call ale#linter#Define('clojure', {
\ 'name': 'clj-kondo',
\ 'output_stream': 'stdout',
\ 'executable': 'clj-kondo',
\ 'command': 'clj-kondo --cache --lint %t',
\ 'callback': 'ale_linters#clojure#clj_kondo#HandleCljKondoFormat',
\})

View File

@@ -9,11 +9,9 @@ function! ale_linters#clojure#joker#HandleJokerFormat(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:type = 'E' let l:type = 'E'
if l:match[4] is? 'Parse warning' if l:match[4] is? 'Parse warning'
let l:type = 'W' let l:type = 'W'
endif endif
call add(l:output, { call add(l:output, {
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'col': l:match[2] + 0, \ 'col': l:match[2] + 0,
@@ -29,6 +27,6 @@ call ale#linter#Define('clojure', {
\ 'name': 'joker', \ 'name': 'joker',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'joker', \ 'executable': 'joker',
\ 'command': 'joker --working-dir %s --lint %t', \ 'command': 'joker --lint %t',
\ 'callback': 'ale_linters#clojure#joker#HandleJokerFormat', \ 'callback': 'ale_linters#clojure#joker#HandleJokerFormat',
\}) \})

View File

@@ -1,35 +0,0 @@
" Author: Yasuhiro Kiyota <yasuhiroki.duck@gmail.com>
" Description: Support cfn-python-lint for AWS Cloudformation template file
function! ale_linters#cloudformation#cfn_python_lint#Handle(buffer, lines) abort
" Matches patterns line the following:
"
" sample.template.yaml:96:7:96:15:E3012:Property Resources/Sample/Properties/FromPort should be of type Integer
let l:pattern = '\v^(.*):(\d+):(\d+):(\d+):(\d+):([[:alnum:]]+):(.*)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:code = l:match[6]
if ale#path#IsBufferPath(a:buffer, l:match[1])
call add(l:output, {
\ 'lnum': l:match[2],
\ 'col': l:match[3],
\ 'end_lnum': l:match[4],
\ 'end_col': l:match[5],
\ 'code': l:code,
\ 'type': l:code[:0] is# 'E' ? 'E' : 'W',
\ 'text': l:match[7]
\})
endif
endfor
return l:output
endfunction
call ale#linter#Define('cloudformation', {
\ 'name': 'cloudformation',
\ 'executable': 'cfn-lint',
\ 'command': 'cfn-lint --template %t --format parseable',
\ 'callback': 'ale_linters#cloudformation#cfn_python_lint#Handle',
\})

View File

@@ -18,7 +18,7 @@ endfunction
call ale#linter#Define('cmake', { call ale#linter#Define('cmake', {
\ 'name': 'cmakelint', \ 'name': 'cmakelint',
\ 'executable': function('ale_linters#cmake#cmakelint#Executable'), \ 'executable_callback': 'ale_linters#cmake#cmakelint#Executable',
\ 'command': function('ale_linters#cmake#cmakelint#Command'), \ 'command_callback': 'ale_linters#cmake#cmakelint#Command',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale#handlers#unix#HandleAsWarning',
\}) \})

View File

@@ -16,8 +16,8 @@ endfunction
call ale#linter#Define('coffee', { call ale#linter#Define('coffee', {
\ 'name': 'coffee', \ 'name': 'coffee',
\ 'executable': function('ale_linters#coffee#coffee#GetExecutable'), \ 'executable_callback': 'ale_linters#coffee#coffee#GetExecutable',
\ 'command': function('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#gcc#HandleGCCFormat',
\}) \})

View File

@@ -37,7 +37,7 @@ endfunction
call ale#linter#Define('coffee', { call ale#linter#Define('coffee', {
\ 'name': 'coffeelint', \ 'name': 'coffeelint',
\ 'executable': function('ale_linters#coffee#coffeelint#GetExecutable'), \ 'executable_callback': 'ale_linters#coffee#coffeelint#GetExecutable',
\ 'command': function('ale_linters#coffee#coffeelint#GetCommand'), \ 'command_callback': 'ale_linters#coffee#coffeelint#GetCommand',
\ 'callback': 'ale_linters#coffee#coffeelint#Handle', \ 'callback': 'ale_linters#coffee#coffeelint#Handle',
\}) \})

View File

@@ -1,14 +0,0 @@
" Author: Ye Jingchen <ye.jingchen@gmail.com>, Ben Falconer <ben@falconers.me.uk>, jtalowell <jtalowell@protonmail.com>
" Description: A language server for C++
call ale#Set('cpp_ccls_executable', 'ccls')
call ale#Set('cpp_ccls_init_options', {})
call ale#linter#Define('cpp', {
\ 'name': 'ccls',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'cpp_ccls_executable')},
\ 'command': '%e',
\ 'project_root': function('ale#handlers#ccls#GetProjectRoot'),
\ 'initialization_options': {b -> ale#Var(b, 'cpp_ccls_init_options')},
\})

View File

@@ -4,21 +4,26 @@
call ale#Set('cpp_clang_executable', 'clang++') call ale#Set('cpp_clang_executable', 'clang++')
call ale#Set('cpp_clang_options', '-std=c++14 -Wall') call ale#Set('cpp_clang_options', '-std=c++14 -Wall')
function! ale_linters#cpp#clang#GetCommand(buffer, output) abort function! ale_linters#cpp#clang#GetExecutable(buffer) abort
let l:cflags = ale#c#GetCFlags(a:buffer, a:output) return ale#Var(a:buffer, 'cpp_clang_executable')
endfunction
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 '%e -S -x c++ -fsyntax-only' return ale#Escape(ale_linters#cpp#clang#GetExecutable(a:buffer))
\ . ' -iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) \ . ' -S -x c++ -fsyntax-only '
\ . ale#Pad(l:cflags) \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' '
\ . ale#Pad(ale#Var(a:buffer, 'cpp_clang_options')) . ' -' \ . ale#c#IncludeOptions(l:paths)
\ . ale#Var(a:buffer, 'cpp_clang_options') . ' -'
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
\ 'name': 'clang', \ 'name': 'clang',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'cpp_clang_executable')}, \ 'executable_callback': 'ale_linters#cpp#clang#GetExecutable',
\ 'command': {b -> ale#c#RunMakeCommand(b, function('ale_linters#cpp#clang#GetCommand'))}, \ 'command_callback': 'ale_linters#cpp#clang#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\}) \})

View File

@@ -5,6 +5,10 @@ call ale#Set('cpp_clangcheck_executable', 'clang-check')
call ale#Set('cpp_clangcheck_options', '') call ale#Set('cpp_clangcheck_options', '')
call ale#Set('c_build_dir', '') 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 function! ale_linters#cpp#clangcheck#GetCommand(buffer) abort
let l:user_options = ale#Var(a:buffer, 'cpp_clangcheck_options') let l:user_options = ale#Var(a:buffer, 'cpp_clangcheck_options')
@@ -12,24 +16,24 @@ function! ale_linters#cpp#clangcheck#GetCommand(buffer) abort
let l:build_dir = ale#Var(a:buffer, 'c_build_dir') let l:build_dir = ale#Var(a:buffer, 'c_build_dir')
if empty(l:build_dir) if empty(l:build_dir)
let [l:root, l:json_file] = ale#c#FindCompileCommands(a:buffer) let l:build_dir = ale#c#FindCompileCommands(a:buffer)
let l:build_dir = ale#path#Dirname(l:json_file)
endif endif
" The extra arguments in the command are used to prevent .plist files from " 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 " being generated. These are only added if no build directory can be
" detected. " detected.
return '%e -analyze %s' return ale#Escape(ale_linters#cpp#clangcheck#GetExecutable(a:buffer))
\ . (empty(l:build_dir) ? ' --extra-arg=-Xclang --extra-arg=-analyzer-output=text --extra-arg=-fno-color-diagnostics': '') \ . ' -analyze %s'
\ . ale#Pad(l:user_options) \ . (empty(l:build_dir) ? ' -extra-arg -Xclang -extra-arg -analyzer-output=text' : '')
\ . (!empty(l:user_options) ? ' ' . l:user_options : '')
\ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '') \ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '')
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
\ 'name': 'clangcheck', \ 'name': 'clangcheck',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'cpp_clangcheck_executable')}, \ 'executable_callback': 'ale_linters#cpp#clangcheck#GetExecutable',
\ 'command': function('ale_linters#cpp#clangcheck#GetCommand'), \ 'command_callback': 'ale_linters#cpp#clangcheck#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\ 'lint_file': 1, \ 'lint_file': 1,
\}) \})

View File

@@ -1,22 +0,0 @@
" Author: Andrey Melentyev <andrey.melentyev@protonmail.com>
" Description: Clangd language server
call ale#Set('cpp_clangd_executable', 'clangd')
call ale#Set('cpp_clangd_options', '')
call ale#Set('c_build_dir', '')
function! ale_linters#cpp#clangd#GetCommand(buffer) abort
let l:build_dir = ale#c#GetBuildDirectory(a:buffer)
return '%e'
\ . ale#Pad(ale#Var(a:buffer, 'cpp_clangd_options'))
\ . (!empty(l:build_dir) ? ' -compile-commands-dir=' . ale#Escape(l:build_dir) : '')
endfunction
call ale#linter#Define('cpp', {
\ 'name': 'clangd',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'cpp_clangd_executable')},
\ 'command': function('ale_linters#cpp#clangd#GetCommand'),
\ 'project_root': function('ale#c#FindProjectRoot'),
\})

View File

@@ -4,33 +4,45 @@
call ale#Set('cpp_clangtidy_executable', 'clang-tidy') call ale#Set('cpp_clangtidy_executable', 'clang-tidy')
" Set this option to check the checks clang-tidy will apply. " Set this option to check the checks clang-tidy will apply.
call ale#Set('cpp_clangtidy_checks', []) call ale#Set('cpp_clangtidy_checks', ['*'])
" Set this option to manually set some options for clang-tidy to use as compile " Set this option to manually set some options for clang-tidy.
" flags.
" This will disable compile_commands.json detection. " This will disable compile_commands.json detection.
call ale#Set('cpp_clangtidy_options', '') call ale#Set('cpp_clangtidy_options', '')
" Set this option to manually set options for clang-tidy directly.
call ale#Set('cpp_clangtidy_extra_options', '')
call ale#Set('c_build_dir', '') call ale#Set('c_build_dir', '')
function! ale_linters#cpp#clangtidy#GetCommand(buffer, output) abort function! ale_linters#cpp#clangtidy#GetExecutable(buffer) abort
let l:checks = join(ale#Var(a:buffer, 'cpp_clangtidy_checks'), ',') return ale#Var(a:buffer, 'cpp_clangtidy_executable')
let l:build_dir = ale#c#GetBuildDirectory(a:buffer) endfunction
let l:options = ''
" Get the extra options if we couldn't find a build directory. function! s:GetBuildDirectory(buffer) abort
if empty(l:build_dir) " Don't include build directory for header files, as compile_commands.json
let l:options = ale#Var(a:buffer, 'cpp_clangtidy_options') " files don't consider headers to be translation units, and provide no
let l:cflags = ale#c#GetCFlags(a:buffer, a:output) " commands for compiling header files.
let l:options .= !empty(l:options) ? ale#Pad(l:cflags) : l:cflags if expand('#' . a:buffer) =~# '\v\.(h|hpp)$'
return ''
endif endif
" Get the options to pass directly to clang-tidy let l:build_dir = ale#Var(a:buffer, 'c_build_dir')
let l:extra_options = ale#Var(a:buffer, 'cpp_clangtidy_extra_options')
return '%e' " 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
let l:checks = join(ale#Var(a:buffer, 'cpp_clangtidy_checks'), ',')
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) : '') \ . (!empty(l:checks) ? ' -checks=' . ale#Escape(l:checks) : '')
\ . (!empty(l:extra_options) ? ' ' . ale#Escape(l:extra_options) : '')
\ . ' %s' \ . ' %s'
\ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '') \ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '')
\ . (!empty(l:options) ? ' -- ' . l:options : '') \ . (!empty(l:options) ? ' -- ' . l:options : '')
@@ -39,8 +51,8 @@ endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
\ 'name': 'clangtidy', \ 'name': 'clangtidy',
\ 'output_stream': 'stdout', \ 'output_stream': 'stdout',
\ 'executable': {b -> ale#Var(b, 'cpp_clangtidy_executable')}, \ 'executable_callback': 'ale_linters#cpp#clangtidy#GetExecutable',
\ 'command': {b -> ale#c#RunMakeCommand(b, function('ale_linters#cpp#clangtidy#GetCommand'))}, \ 'command_callback': 'ale_linters#cpp#clangtidy#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\ 'lint_file': 1, \ 'lint_file': 1,
\}) \})

View File

@@ -1,32 +0,0 @@
" Description: clazy linter for cpp files (clang-based and Qt-oriented)
call ale#Set('cpp_clazy_executable', 'clazy-standalone')
" Set this option to check the checks clazy will apply.
call ale#Set('cpp_clazy_checks', ['level1'])
" Set this option to manually set some options for clazy.
" This will disable compile_commands.json detection.
call ale#Set('cpp_clazy_options', '')
call ale#Set('c_build_dir', '')
function! ale_linters#cpp#clazy#GetCommand(buffer) abort
let l:checks = join(ale#Var(a:buffer, 'cpp_clazy_checks'), ',')
let l:build_dir = ale#c#GetBuildDirectory(a:buffer)
" Get the extra options if we couldn't find a build directory.
let l:options = ale#Var(a:buffer, 'cpp_clazy_options')
return '%e'
\ . (!empty(l:checks) ? ' -checks=' . ale#Escape(l:checks) : '')
\ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '')
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %s'
endfunction
call ale#linter#Define('cpp', {
\ 'name': 'clazy',
\ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'cpp_clazy_executable')},
\ 'command': function('ale_linters#cpp#clazy#GetCommand'),
\ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\ 'lint_file': 1,
\})

View File

@@ -4,25 +4,36 @@
call ale#Set('cpp_cppcheck_executable', 'cppcheck') call ale#Set('cpp_cppcheck_executable', 'cppcheck')
call ale#Set('cpp_cppcheck_options', '--enable=style') call ale#Set('cpp_cppcheck_options', '--enable=style')
function! ale_linters#cpp#cppcheck#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cpp_cppcheck_executable')
endfunction
function! ale_linters#cpp#cppcheck#GetCommand(buffer) abort function! ale_linters#cpp#cppcheck#GetCommand(buffer) abort
let l:cd_command = ale#handlers#cppcheck#GetCdCommand(a:buffer) " Search upwards from the file for compile_commands.json.
let l:compile_commands_option = ale#handlers#cppcheck#GetCompileCommandsOptions(a:buffer) "
let l:buffer_path_include = empty(l:compile_commands_option) " If we find it, we'll `cd` to where the compile_commands.json file is,
\ ? ale#handlers#cppcheck#GetBufferPathIncludeOptions(a:buffer) " 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 return l:cd_command
\ . '%e -q --language=c++' \ . ale#Escape(ale_linters#cpp#cppcheck#GetExecutable(a:buffer))
\ . ale#Pad(l:compile_commands_option) \ . ' -q --language=c++ '
\ . ale#Pad(ale#Var(a:buffer, 'cpp_cppcheck_options')) \ . l:compile_commands_option
\ . l:buffer_path_include \ . ale#Var(a:buffer, 'cpp_cppcheck_options')
\ . ' %t' \ . ' %t'
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
\ 'name': 'cppcheck', \ 'name': 'cppcheck',
\ 'output_stream': 'both', \ 'output_stream': 'both',
\ 'executable': {b -> ale#Var(b, 'cpp_cppcheck_executable')}, \ 'executable_callback': 'ale_linters#cpp#cppcheck#GetExecutable',
\ 'command': function('ale_linters#cpp#cppcheck#GetCommand'), \ 'command_callback': 'ale_linters#cpp#cppcheck#GetCommand',
\ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat', \ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat',
\}) \})

View File

@@ -4,17 +4,23 @@
call ale#Set('cpp_cpplint_executable', 'cpplint') call ale#Set('cpp_cpplint_executable', 'cpplint')
call ale#Set('cpp_cpplint_options', '') 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 function! ale_linters#cpp#cpplint#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'cpp_cpplint_options') let l:options = ale#Var(a:buffer, 'cpp_cpplint_options')
return '%e' . ale#Pad(l:options) . ' %s' return ale#Escape(ale_linters#cpp#cpplint#GetExecutable(a:buffer))
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %s'
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
\ 'name': 'cpplint', \ 'name': 'cpplint',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'cpp_cpplint_executable')}, \ 'executable_callback': 'ale_linters#cpp#cpplint#GetExecutable',
\ 'command': function('ale_linters#cpp#cpplint#GetCommand'), \ 'command_callback': 'ale_linters#cpp#cpplint#GetCommand',
\ 'callback': 'ale#handlers#cpplint#HandleCppLintFormat', \ 'callback': 'ale#handlers#cpplint#HandleCppLintFormat',
\ 'lint_file': 1, \ 'lint_file': 1,
\}) \})

View File

@@ -1,30 +0,0 @@
" Author: Ben Falconer <ben@falconers.me.uk>
" Description: A language server for C++
call ale#Set('cpp_cquery_executable', 'cquery')
call ale#Set('cpp_cquery_cache_directory', expand('~/.cache/cquery'))
function! ale_linters#cpp#cquery#GetProjectRoot(buffer) abort
" Try to find cquery configuration files first.
let l:config = ale#path#FindNearestFile(a:buffer, '.cquery')
if !empty(l:config)
return fnamemodify(l:config, ':h')
endif
" Fall back on default project root detection.
return ale#c#FindProjectRoot(a:buffer)
endfunction
function! ale_linters#cpp#cquery#GetInitializationOptions(buffer) abort
return {'cacheDirectory': ale#Var(a:buffer, 'cpp_cquery_cache_directory')}
endfunction
call ale#linter#Define('cpp', {
\ 'name': 'cquery',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'cpp_cquery_executable')},
\ 'command': '%e',
\ 'project_root': function('ale_linters#cpp#cquery#GetProjectRoot'),
\ 'initialization_options': function('ale_linters#cpp#cquery#GetInitializationOptions'),
\})

View File

@@ -6,20 +6,26 @@ call ale#Set('cpp_flawfinder_options', '')
call ale#Set('cpp_flawfinder_minlevel', 1) call ale#Set('cpp_flawfinder_minlevel', 1)
call ale#Set('c_flawfinder_error_severity', 6) call ale#Set('c_flawfinder_error_severity', 6)
function! ale_linters#cpp#flawfinder#GetCommand(buffer) abort function! ale_linters#cpp#flawfinder#GetExecutable(buffer) abort
" Set the minimum vulnerability level for flawfinder to bother with return ale#Var(a:buffer, 'cpp_flawfinder_executable')
let l:minlevel = ' --minlevel=' . ale#Var(a:buffer, 'cpp_flawfinder_minlevel') endfunction
return '%e -CDQS' function! ale_linters#cpp#flawfinder#GetCommand(buffer) abort
\ . ale#Var(a:buffer, 'cpp_flawfinder_options')
\ . l:minlevel " Set the minimum vulnerability level for flawfinder to bother with
\ . ' %t' let l:minlevel = ' --minlevel=' . ale#Var(a:buffer, 'cpp_flawfinder_minlevel')
return ale#Escape(ale_linters#cpp#flawfinder#GetExecutable(a:buffer))
\ . ' -CDQS'
\ . ale#Var(a:buffer, 'cpp_flawfinder_options')
\ . l:minlevel
\ . ' %t'
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
\ 'name': 'flawfinder', \ 'name': 'flawfinder',
\ 'output_stream': 'stdout', \ 'output_stream': 'stdout',
\ 'executable': {b -> ale#Var(b, 'cpp_flawfinder_executable')}, \ 'executable_callback': 'ale_linters#cpp#flawfinder#GetExecutable',
\ 'command': function('ale_linters#cpp#flawfinder#GetCommand'), \ 'command_callback': 'ale_linters#cpp#flawfinder#GetCommand',
\ 'callback': 'ale#handlers#flawfinder#HandleFlawfinderFormat', \ 'callback': 'ale#handlers#flawfinder#HandleFlawfinderFormat',
\}) \})

View File

@@ -4,26 +4,26 @@
call ale#Set('cpp_gcc_executable', 'gcc') call ale#Set('cpp_gcc_executable', 'gcc')
call ale#Set('cpp_gcc_options', '-std=c++14 -Wall') call ale#Set('cpp_gcc_options', '-std=c++14 -Wall')
function! ale_linters#cpp#gcc#GetCommand(buffer, output) abort function! ale_linters#cpp#gcc#GetExecutable(buffer) abort
let l:cflags = ale#c#GetCFlags(a:buffer, a:output) return ale#Var(a:buffer, 'cpp_gcc_executable')
endfunction
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))
" `-o /dev/null` or `-o null` is needed to catch all errors, \ . ' -S -x c++ -fsyntax-only '
" -fsyntax-only doesn't catch everything. \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' '
return '%e -S -x c++' \ . ale#c#IncludeOptions(l:paths)
\ . ' -o ' . g:ale#util#nul_file \ . ale#Var(a:buffer, 'cpp_gcc_options') . ' -'
\ . ' -iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h'))
\ . ale#Pad(l:cflags)
\ . ale#Pad(ale#Var(a:buffer, 'cpp_gcc_options')) . ' -'
endfunction endfunction
call ale#linter#Define('cpp', { call ale#linter#Define('cpp', {
\ 'name': 'gcc', \ 'name': 'g++',
\ 'aliases': ['g++'],
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'cpp_gcc_executable')}, \ 'executable_callback': 'ale_linters#cpp#gcc#GetExecutable',
\ 'command': {b -> ale#c#RunMakeCommand(b, function('ale_linters#cpp#gcc#GetCommand'))}, \ 'command_callback': 'ale_linters#cpp#gcc#GetCommand',
\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat',
\}) \})

View File

@@ -1,57 +0,0 @@
" Author: Harrison Bachrach - https://github.com/HarrisonB
" Description: Ameba, a linter for crystal files
call ale#Set('crystal_ameba_executable', 'bin/ameba')
function! ale_linters#crystal#ameba#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'crystal_ameba_executable')
return ale#Escape(l:executable)
\ . ' --format json '
\ . ale#Escape(expand('#' . a:buffer . ':p'))
endfunction
" Handle output from ameba
function! ale_linters#crystal#ameba#HandleAmebaOutput(buffer, lines) abort
if len(a:lines) == 0
return []
endif
let l:errors = ale#util#FuzzyJSONDecode(a:lines[0], {})
if !has_key(l:errors, 'summary')
\|| l:errors['summary']['issues_count'] == 0
\|| empty(l:errors['sources'])
return []
endif
let l:output = []
for l:error in l:errors['sources'][0]['issues']
let l:start_col = str2nr(l:error['location']['column'])
let l:end_col = str2nr(l:error['end_location']['column'])
if !l:end_col
let l:end_col = l:start_col + 1
endif
call add(l:output, {
\ 'lnum': str2nr(l:error['location']['line']),
\ 'col': l:start_col,
\ 'end_col': l:end_col,
\ 'code': l:error['rule_name'],
\ 'text': l:error['message'],
\ 'type': 'W',
\})
endfor
return l:output
endfunction
call ale#linter#Define('crystal', {
\ 'name': 'ameba',
\ 'executable': {b -> ale#Var(b, 'crystal_ameba_executable')},
\ 'command': function('ale_linters#crystal#ameba#GetCommand'),
\ 'callback': 'ale_linters#crystal#ameba#HandleAmebaOutput',
\ 'lint_file': 1,
\})

View File

@@ -5,10 +5,6 @@ function! ale_linters#crystal#crystal#Handle(buffer, lines) abort
let l:output = [] let l:output = []
for l:error in ale#util#FuzzyJSONDecode(a:lines, []) for l:error in ale#util#FuzzyJSONDecode(a:lines, [])
if !has_key(l:error, 'file')
continue
endif
call add(l:output, { call add(l:output, {
\ 'lnum': l:error.line + 0, \ 'lnum': l:error.line + 0,
\ 'col': l:error.column + 0, \ 'col': l:error.column + 0,
@@ -30,6 +26,6 @@ call ale#linter#Define('crystal', {
\ 'executable': 'crystal', \ 'executable': 'crystal',
\ 'output_stream': 'both', \ 'output_stream': 'both',
\ 'lint_file': 1, \ 'lint_file': 1,
\ 'command': function('ale_linters#crystal#crystal#GetCommand'), \ 'command_callback': 'ale_linters#crystal#crystal#GetCommand',
\ 'callback': 'ale_linters#crystal#crystal#Handle', \ 'callback': 'ale_linters#crystal#crystal#Handle',
\}) \})

View File

@@ -1,95 +0,0 @@
call ale#Set('cs_csc_options', '')
call ale#Set('cs_csc_source', '')
call ale#Set('cs_csc_assembly_path', [])
call ale#Set('cs_csc_assemblies', [])
function! s:GetWorkingDirectory(buffer) abort
let l:working_directory = ale#Var(a:buffer, 'cs_csc_source')
if !empty(l:working_directory)
return l:working_directory
endif
return expand('#' . a:buffer . ':p:h')
endfunction
function! ale_linters#cs#csc#GetCommand(buffer) abort
" Pass assembly paths via the -lib: parameter.
let l:path_list = ale#Var(a:buffer, 'cs_csc_assembly_path')
let l:lib_option = !empty(l:path_list)
\ ? '/lib:' . join(map(copy(l:path_list), 'ale#Escape(v:val)'), ',')
\ : ''
" Pass paths to DLL files via the -r: parameter.
let l:assembly_list = ale#Var(a:buffer, 'cs_csc_assemblies')
let l:r_option = !empty(l:assembly_list)
\ ? '/r:' . join(map(copy(l:assembly_list), 'ale#Escape(v:val)'), ',')
\ : ''
" register temporary module target file with ale
" register temporary module target file with ALE.
let l:out = ale#command#CreateFile(a:buffer)
" The code is compiled as a module and the output is redirected to a
" temporary file.
return ale#path#CdString(s:GetWorkingDirectory(a:buffer))
\ . 'csc /unsafe'
\ . ale#Pad(ale#Var(a:buffer, 'cs_csc_options'))
\ . ale#Pad(l:lib_option)
\ . ale#Pad(l:r_option)
\ . ' /out:' . l:out
\ . ' /t:module'
\ . ' /recurse:' . ale#Escape('*.cs')
endfunction
function! ale_linters#cs#csc#Handle(buffer, lines) abort
" Look for lines like the following.
"
" Tests.cs(12,29): error CSXXXX: ; expected
"
" NOTE: pattern also captures file name as linter compiles all
" files within the source tree rooted at the specified source
" path and not just the file loaded in the buffer
let l:patterns = [
\ '^\v(.+\.cs)\((\d+),(\d+)\)\:\s+([^ ]+)\s+([cC][sS][^ ]+):\s(.+)$',
\ '^\v([^ ]+)\s+([Cc][sS][^ ]+):\s+(.+)$',
\]
let l:output = []
let l:dir = s:GetWorkingDirectory(a:buffer)
for l:match in ale#util#GetMatches(a:lines, l:patterns)
if len(l:match) > 6 && strlen(l:match[5]) > 2 && l:match[5][:1] is? 'CS'
call add(l:output, {
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]),
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'type': l:match[4] is# 'error' ? 'E' : 'W',
\ 'code': l:match[5],
\ 'text': l:match[6] ,
\})
elseif strlen(l:match[2]) > 2 && l:match[2][:1] is? 'CS'
call add(l:output, {
\ 'filename':'<csc>',
\ 'lnum': -1,
\ 'col': -1,
\ 'type': l:match[1] is# 'error' ? 'E' : 'W',
\ 'code': l:match[2],
\ 'text': l:match[3],
\})
endif
endfor
return l:output
endfunction
call ale#linter#Define('cs',{
\ 'name': 'csc',
\ 'output_stream': 'stdout',
\ 'executable': 'csc',
\ 'command': function('ale_linters#cs#csc#GetCommand'),
\ 'callback': 'ale_linters#cs#csc#Handle',
\ 'lint_file': 1
\})

View File

@@ -1,11 +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
let l:options = ale#Var(a:buffer, 'cs_mcs_options') return 'mcs -unsafe --parse ' . ale#Var(a:buffer, 'cs_mcs_options') . ' %t'
return 'mcs -unsafe --parse'
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %t'
endfunction endfunction
function! ale_linters#cs#mcs#Handle(buffer, lines) abort function! ale_linters#cs#mcs#Handle(buffer, lines) abort
@@ -32,6 +28,6 @@ call ale#linter#Define('cs',{
\ 'name': 'mcs', \ 'name': 'mcs',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'mcs', \ 'executable': 'mcs',
\ 'command': function('ale_linters#cs#mcs#GetCommand'), \ 'command_callback': 'ale_linters#cs#mcs#GetCommand',
\ 'callback': 'ale_linters#cs#mcs#Handle', \ 'callback': 'ale_linters#cs#mcs#Handle',
\}) \})

View File

@@ -29,16 +29,16 @@ function! ale_linters#cs#mcsc#GetCommand(buffer) abort
\ : '' \ : ''
" register temporary module target file with ale " register temporary module target file with ale
" register temporary module target file with ALE. let l:out = tempname()
let l:out = ale#command#CreateFile(a:buffer) call ale#engine#ManageFile(a:buffer, l:out)
" The code is compiled as a module and the output is redirected to a " The code is compiled as a module and the output is redirected to a
" temporary file. " temporary file.
return ale#path#CdString(s:GetWorkingDirectory(a:buffer)) return ale#path#CdString(s:GetWorkingDirectory(a:buffer))
\ . 'mcs -unsafe' \ . 'mcs -unsafe'
\ . ale#Pad(ale#Var(a:buffer, 'cs_mcsc_options')) \ . ' ' . ale#Var(a:buffer, 'cs_mcsc_options')
\ . ale#Pad(l:lib_option) \ . ' ' . l:lib_option
\ . ale#Pad(l:r_option) \ . ' ' . l:r_option
\ . ' -out:' . l:out \ . ' -out:' . l:out
\ . ' -t:module' \ . ' -t:module'
\ . ' -recurse:' . ale#Escape('*.cs') \ . ' -recurse:' . ale#Escape('*.cs')
@@ -52,34 +52,20 @@ function! ale_linters#cs#mcsc#Handle(buffer, lines) abort
" NOTE: pattern also captures file name as linter compiles all " NOTE: pattern also captures file name as linter compiles all
" files within the source tree rooted at the specified source " files within the source tree rooted at the specified source
" path and not just the file loaded in the buffer " path and not just the file loaded in the buffer
let l:patterns = [ let l:pattern = '^\v(.+\.cs)\((\d+),(\d+)\)\: ([^ ]+) ([^ ]+): (.+)$'
\ '^\v(.+\.cs)\((\d+),(\d+)\)\:\s+([^ ]+)\s+([cC][sS][^ ]+):\s(.+)$',
\ '^\v([^ ]+)\s+([Cc][sS][^ ]+):\s+(.+)$',
\]
let l:output = [] let l:output = []
let l:dir = s:GetWorkingDirectory(a:buffer) let l:dir = s:GetWorkingDirectory(a:buffer)
for l:match in ale#util#GetMatches(a:lines, l:patterns) for l:match in ale#util#GetMatches(a:lines, l:pattern)
if len(l:match) > 6 && strlen(l:match[5]) > 2 && l:match[5][:1] is? 'CS' call add(l:output, {
call add(l:output, { \ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]),
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]), \ 'lnum': l:match[2] + 0,
\ 'lnum': l:match[2] + 0, \ 'col': l:match[3] + 0,
\ 'col': l:match[3] + 0, \ 'type': l:match[4] is# 'error' ? 'E' : 'W',
\ 'type': l:match[4] is# 'error' ? 'E' : 'W', \ 'code': l:match[5],
\ 'code': l:match[5], \ 'text': l:match[6],
\ 'text': l:match[6] , \})
\})
elseif strlen(l:match[2]) > 2 && l:match[2][:1] is? 'CS'
call add(l:output, {
\ 'filename':'<mcs>',
\ 'lnum': -1,
\ 'col': -1,
\ 'type': l:match[1] is# 'error' ? 'E' : 'W',
\ 'code': l:match[2],
\ 'text': l:match[3],
\})
endif
endfor endfor
return l:output return l:output
@@ -89,7 +75,7 @@ call ale#linter#Define('cs',{
\ 'name': 'mcsc', \ 'name': 'mcsc',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'mcs', \ 'executable': 'mcs',
\ 'command': function('ale_linters#cs#mcsc#GetCommand'), \ 'command_callback': 'ale_linters#cs#mcsc#GetCommand',
\ 'callback': 'ale_linters#cs#mcsc#Handle', \ 'callback': 'ale_linters#cs#mcsc#Handle',
\ 'lint_file': 1 \ 'lint_file': 1
\}) \})

View File

@@ -13,6 +13,6 @@ endfunction
call ale#linter#Define('css', { call ale#linter#Define('css', {
\ 'name': 'csslint', \ 'name': 'csslint',
\ 'executable': 'csslint', \ 'executable': 'csslint',
\ 'command': function('ale_linters#css#csslint#GetCommand'), \ 'command_callback': 'ale_linters#css#csslint#GetCommand',
\ 'callback': 'ale#handlers#css#HandleCSSLintFormat', \ 'callback': 'ale#handlers#css#HandleCSSLintFormat',
\}) \})

View File

@@ -1,9 +0,0 @@
" Author: harttle <yangjvn@126.com>
" Description: fecs for CSS files
call ale#linter#Define('css', {
\ 'name': 'fecs',
\ 'executable': function('ale#handlers#fecs#GetExecutable'),
\ 'command': function('ale#handlers#fecs#GetCommand'),
\ 'callback': 'ale#handlers#fecs#Handle',
\})

View File

@@ -2,18 +2,23 @@
call ale#Set('css_stylelint_executable', 'stylelint') call ale#Set('css_stylelint_executable', 'stylelint')
call ale#Set('css_stylelint_options', '') call ale#Set('css_stylelint_options', '')
call ale#Set('css_stylelint_use_global', get(g:, 'ale_use_global_executables', 0)) call ale#Set('css_stylelint_use_global', 0)
function! ale_linters#css#stylelint#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'css_stylelint', [
\ 'node_modules/.bin/stylelint',
\])
endfunction
function! ale_linters#css#stylelint#GetCommand(buffer) abort function! ale_linters#css#stylelint#GetCommand(buffer) abort
return '%e ' . ale#Pad(ale#Var(a:buffer, 'css_stylelint_options')) return ale_linters#css#stylelint#GetExecutable(a:buffer)
\ . ' ' . ale#Var(a:buffer, 'css_stylelint_options')
\ . ' --stdin-filename %s' \ . ' --stdin-filename %s'
endfunction endfunction
call ale#linter#Define('css', { call ale#linter#Define('css', {
\ 'name': 'stylelint', \ 'name': 'stylelint',
\ 'executable': {b -> ale#node#FindExecutable(b, 'css_stylelint', [ \ 'executable_callback': 'ale_linters#css#stylelint#GetExecutable',
\ 'node_modules/.bin/stylelint', \ 'command_callback': 'ale_linters#css#stylelint#GetCommand',
\ ])},
\ 'command': function('ale_linters#css#stylelint#GetCommand'),
\ 'callback': 'ale#handlers#css#HandleStyleLintFormat', \ 'callback': 'ale#handlers#css#HandleStyleLintFormat',
\}) \})

View File

@@ -1,46 +0,0 @@
" Author: Eddie Lebow https://github.com/elebow
" Description: Cucumber, a BDD test tool
function! ale_linters#cucumber#cucumber#GetCommand(buffer) abort
let l:features_dir = ale#path#FindNearestDirectory(a:buffer, 'features')
if !empty(l:features_dir)
let l:features_arg = '-r ' . ale#Escape(l:features_dir)
else
let l:features_arg = ''
endif
return 'cucumber --dry-run --quiet --strict --format=json '
\ . l:features_arg . ' %t'
endfunction
function! ale_linters#cucumber#cucumber#Handle(buffer, lines) abort
try
let l:json = ale#util#FuzzyJSONDecode(a:lines, {})[0]
catch
return []
endtry
let l:output = []
for l:element in get(l:json, 'elements', [])
for l:step in l:element['steps']
if l:step['result']['status'] is# 'undefined'
call add(l:output, {
\ 'lnum': l:step['line'],
\ 'code': 'E',
\ 'text': 'Undefined step'
\})
endif
endfor
endfor
return l:output
endfunction
call ale#linter#Define('cucumber', {
\ 'name': 'cucumber',
\ 'executable': 'cucumber',
\ 'command': function('ale_linters#cucumber#cucumber#GetCommand'),
\ 'callback': 'ale_linters#cucumber#cucumber#Handle'
\})

View File

@@ -4,14 +4,20 @@
call ale#Set('cuda_nvcc_executable', 'nvcc') call ale#Set('cuda_nvcc_executable', 'nvcc')
call ale#Set('cuda_nvcc_options', '-std=c++11') call ale#Set('cuda_nvcc_options', '-std=c++11')
function! ale_linters#cuda#nvcc#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'cuda_nvcc_executable')
endfunction
function! ale_linters#cuda#nvcc#GetCommand(buffer) abort function! ale_linters#cuda#nvcc#GetCommand(buffer) abort
" Unused: use ale#util#nul_file " Unused: use ale#util#nul_file
" let l:output_file = ale#util#Tempname() . '.ii' " let l:output_file = tempname() . '.ii'
" call ale#command#ManageFile(a:buffer, l:output_file) " call ale#engine#ManageFile(a:buffer, l:output_file)
return '%e -cuda'
\ . ale#Pad(ale#c#IncludeOptions(ale#c#FindLocalHeaderPaths(a:buffer))) return ale#Escape(ale_linters#cuda#nvcc#GetExecutable(a:buffer))
\ . ale#Pad(ale#Var(a:buffer, 'cuda_nvcc_options')) \ . ' -cuda '
\ . ' %s -o ' . g:ale#util#nul_file \ . ale#c#IncludeOptions(ale#c#FindLocalHeaderPaths(a:buffer))
\ . ale#Var(a:buffer, 'cuda_nvcc_options') . ' %s'
\ . ' -o ' . g:ale#util#nul_file
endfunction endfunction
function! ale_linters#cuda#nvcc#HandleNVCCFormat(buffer, lines) abort function! ale_linters#cuda#nvcc#HandleNVCCFormat(buffer, lines) abort
@@ -22,6 +28,7 @@ function! ale_linters#cuda#nvcc#HandleNVCCFormat(buffer, lines) abort
let l:output = [] let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:item = { let l:item = {
\ 'lnum': str2nr(l:match[2]), \ 'lnum': str2nr(l:match[2]),
\ 'type': l:match[4] =~# 'error' ? 'E' : 'W', \ 'type': l:match[4] =~# 'error' ? 'E' : 'W',
@@ -42,8 +49,8 @@ endfunction
call ale#linter#Define('cuda', { call ale#linter#Define('cuda', {
\ 'name': 'nvcc', \ 'name': 'nvcc',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'cuda_nvcc_executable')}, \ 'executable_callback': 'ale_linters#cuda#nvcc#GetExecutable',
\ 'command': function('ale_linters#cuda#nvcc#GetCommand'), \ 'command_callback': 'ale_linters#cuda#nvcc#GetCommand',
\ 'callback': 'ale_linters#cuda#nvcc#HandleNVCCFormat', \ 'callback': 'ale_linters#cuda#nvcc#HandleNVCCFormat',
\ 'lint_file': 1, \ 'lint_file': 1,
\}) \})

View File

@@ -1,26 +0,0 @@
" Author: Francisco Lopes <francisco@oblita.com>
" Description: Linting for Neo4j's Cypher
function! ale_linters#cypher#cypher_lint#Handle(buffer, lines) abort
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):(\d+): (.*)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'text': l:match[4],
\ 'type': 'E',
\})
endfor
return l:output
endfunction
call ale#linter#Define('cypher', {
\ 'name': 'cypher_lint',
\ 'executable': 'cypher-lint',
\ 'command': 'cypher-lint',
\ 'output_stream': 'stderr',
\ 'callback': 'ale_linters#cypher#cypher_lint#Handle',
\})

View File

@@ -1,22 +0,0 @@
" Author: aurieh <me@aurieh.me>
" Description: A Language Server implementation for D
call ale#Set('d_dls_executable', 'dls')
function! ale_linters#d#dls#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'd_dls_executable')
endfunction
function! ale_linters#d#dls#FindProjectRoot(buffer) abort
" Note: this will return . if dub config is empty
" dls can run outside DUB projects just fine
return fnamemodify(ale#d#FindDUBConfig(a:buffer), ':h')
endfunction
call ale#linter#Define('d', {
\ 'name': 'dls',
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#d#dls#GetExecutable'),
\ 'command': function('ale_linters#d#dls#GetExecutable'),
\ 'project_root': function('ale_linters#d#dls#FindProjectRoot'),
\})

View File

@@ -1,14 +1,28 @@
" Author: w0rp <devw0rp@gmail.com> " Author: w0rp <devw0rp@gmail.com>
" Description: "dmd for D files" " Description: "dmd for D files"
function! ale_linters#d#dmd#GetDUBCommand(buffer) abort function! s:FindDUBConfig(buffer) abort
" Find a DUB configuration file in ancestor paths.
" The most DUB-specific names will be tried first.
for l:possible_filename in ['dub.sdl', 'dub.json', 'package.json']
let l:dub_file = ale#path#FindNearestFile(a:buffer, l:possible_filename)
if !empty(l:dub_file)
return l:dub_file
endif
endfor
return ''
endfunction
function! ale_linters#d#dmd#DUBCommand(buffer) abort
" If we can't run dub, then skip this command. " If we can't run dub, then skip this command.
if !executable('dub') if !executable('dub')
" Returning an empty string skips to the DMD command. " Returning an empty string skips to the DMD command.
return '' return ''
endif endif
let l:dub_file = ale#d#FindDUBConfig(a:buffer) let l:dub_file = s:FindDUBConfig(a:buffer)
if empty(l:dub_file) if empty(l:dub_file)
return '' return ''
@@ -21,18 +35,7 @@ function! ale_linters#d#dmd#GetDUBCommand(buffer) abort
\ . ' && dub describe --import-paths' \ . ' && dub describe --import-paths'
endfunction endfunction
function! ale_linters#d#dmd#RunDUBCommand(buffer) abort function! ale_linters#d#dmd#DMDCommand(buffer, dub_output) abort
let l:command = ale_linters#d#dmd#GetDUBCommand(a:buffer)
if empty(l:command)
" If we can't run DUB, just run DMD.
return ale_linters#d#dmd#DMDCommand(a:buffer, [], {})
endif
return ale#command#Run(a:buffer, l:command, function('ale_linters#d#dmd#DMDCommand'))
endfunction
function! ale_linters#d#dmd#DMDCommand(buffer, dub_output, meta) abort
let l:import_list = [] let l:import_list = []
" Build a list of import paths generated from DUB, if available. " Build a list of import paths generated from DUB, if available.
@@ -43,7 +46,7 @@ function! ale_linters#d#dmd#DMDCommand(buffer, dub_output, meta) abort
endif endif
endfor endfor
return 'dmd '. join(l:import_list) . ' -o- -wi -vcolumns -c %t' return 'dmd '. join(l:import_list) . ' -o- -vcolumns -c %t'
endfunction endfunction
function! ale_linters#d#dmd#Handle(buffer, lines) abort function! ale_linters#d#dmd#Handle(buffer, lines) abort
@@ -68,7 +71,9 @@ endfunction
call ale#linter#Define('d', { call ale#linter#Define('d', {
\ 'name': 'dmd', \ 'name': 'dmd',
\ 'executable': 'dmd', \ 'executable': 'dmd',
\ 'command': function('ale_linters#d#dmd#RunDUBCommand'), \ 'command_chain': [
\ {'callback': 'ale_linters#d#dmd#DUBCommand', 'output_stream': 'stdout'},
\ {'callback': 'ale_linters#d#dmd#DMDCommand', 'output_stream': 'stderr'},
\ ],
\ 'callback': 'ale_linters#d#dmd#Handle', \ 'callback': 'ale_linters#d#dmd#Handle',
\ 'output_stream': 'stderr',
\}) \})

View File

@@ -13,7 +13,6 @@ function! ale_linters#dafny#dafny#Handle(buffer, lines) abort
\ 'type': l:match[4] =~# '^Error' ? 'E' : 'W' \ 'type': l:match[4] =~# '^Error' ? 'E' : 'W'
\ }) \ })
endfor endfor
return l:output return l:output
endfunction endfunction

View File

@@ -3,10 +3,15 @@
call ale#Set('dart_dartanalyzer_executable', '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 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') let l:path = ale#path#FindNearestFile(a:buffer, '.packages')
return '%e' return ale#Escape(l:executable)
\ . (!empty(l:path) ? ' --packages ' . ale#Escape(l:path) : '') \ . (!empty(l:path) ? ' --packages ' . ale#Escape(l:path) : '')
\ . ' %s' \ . ' %s'
endfunction endfunction
@@ -29,8 +34,8 @@ endfunction
call ale#linter#Define('dart', { call ale#linter#Define('dart', {
\ 'name': 'dartanalyzer', \ 'name': 'dartanalyzer',
\ 'executable': {b -> ale#Var(b, 'dart_dartanalyzer_executable')}, \ 'executable_callback': 'ale_linters#dart#dartanalyzer#GetExecutable',
\ 'command': function('ale_linters#dart#dartanalyzer#GetCommand'), \ 'command_callback': 'ale_linters#dart#dartanalyzer#GetCommand',
\ 'callback': 'ale_linters#dart#dartanalyzer#Handle', \ 'callback': 'ale_linters#dart#dartanalyzer#Handle',
\ 'lint_file': 1, \ 'lint_file': 1,
\}) \})

View File

@@ -3,6 +3,14 @@
call ale#Set('dart_language_server_executable', 'dart_language_server') call ale#Set('dart_language_server_executable', 'dart_language_server')
function! ale_linters#dart#language_server#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'dart_language_server_executable')
endfunction
function! ale_linters#dart#language_server#GetLanguage(buffer) abort
return 'dart'
endfunction
function! ale_linters#dart#language_server#GetProjectRoot(buffer) abort function! ale_linters#dart#language_server#GetProjectRoot(buffer) abort
" Note: pub only looks for pubspec.yaml, there's no point in adding " Note: pub only looks for pubspec.yaml, there's no point in adding
" support for pubspec.yml " support for pubspec.yml
@@ -14,7 +22,9 @@ endfunction
call ale#linter#Define('dart', { call ale#linter#Define('dart', {
\ 'name': 'language_server', \ 'name': 'language_server',
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'dart_language_server_executable')}, \ 'executable_callback': 'ale_linters#dart#language_server#GetExecutable',
\ 'command': '%e', \ 'command_callback': 'ale_linters#dart#language_server#GetExecutable',
\ 'project_root': function('ale_linters#dart#language_server#GetProjectRoot'), \ 'language_callback': 'ale_linters#dart#language_server#GetLanguage',
\ 'project_root_callback': 'ale_linters#dart#language_server#GetProjectRoot',
\}) \})

View File

@@ -1,61 +0,0 @@
" Author: Alexander Olofsson <alexander.olofsson@liu.se>
call ale#Set('dockerfile_dockerfile_lint_executable', 'dockerfile_lint')
call ale#Set('dockerfile_dockerfile_lint_options', '')
function! ale_linters#dockerfile#dockerfile_lint#GetType(type) abort
if a:type is? 'error'
return 'E'
elseif a:type is? 'warn'
return 'W'
endif
return 'I'
endfunction
function! ale_linters#dockerfile#dockerfile_lint#Handle(buffer, lines) abort
try
let l:data = json_decode(join(a:lines, ''))
catch
return []
endtry
if empty(l:data)
" Should never happen, but it's better to be on the safe side
return []
endif
let l:messages = []
for l:type in ['error', 'warn', 'info']
for l:object in l:data[l:type]['data']
let l:line = get(l:object, 'line', -1)
let l:message = l:object['message']
if get(l:object, 'description', 'None') isnot# 'None'
let l:message = l:message . '. ' . l:object['description']
endif
call add(l:messages, {
\ 'lnum': l:line,
\ 'text': l:message,
\ 'type': ale_linters#dockerfile#dockerfile_lint#GetType(l:type),
\})
endfor
endfor
return l:messages
endfunction
function! ale_linters#dockerfile#dockerfile_lint#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'dockerfile_dockerfile_lint_options'))
\ . ' -p -j -f'
\ . ' %t'
endfunction
call ale#linter#Define('dockerfile', {
\ 'name': 'dockerfile_lint',
\ 'executable': {b -> ale#Var(b, 'dockerfile_dockerfile_lint_executable')},
\ 'command': function('ale_linters#dockerfile#dockerfile_lint#GetCommand'),
\ 'callback': 'ale_linters#dockerfile#dockerfile_lint#Handle',
\})

View File

@@ -82,18 +82,16 @@ endfunction
function! ale_linters#dockerfile#hadolint#GetCommand(buffer) abort function! ale_linters#dockerfile#hadolint#GetCommand(buffer) abort
let l:command = ale_linters#dockerfile#hadolint#GetExecutable(a:buffer) let l:command = ale_linters#dockerfile#hadolint#GetExecutable(a:buffer)
if l:command is# 'docker' if l:command is# 'docker'
return 'docker run --rm -i ' . ale#Var(a:buffer, 'dockerfile_hadolint_docker_image') return 'docker run --rm -i ' . ale#Var(a:buffer, 'dockerfile_hadolint_docker_image')
endif endif
return 'hadolint -' return 'hadolint -'
endfunction endfunction
call ale#linter#Define('dockerfile', { call ale#linter#Define('dockerfile', {
\ 'name': 'hadolint', \ 'name': 'hadolint',
\ 'executable': function('ale_linters#dockerfile#hadolint#GetExecutable'), \ 'executable_callback': 'ale_linters#dockerfile#hadolint#GetExecutable',
\ 'command': function('ale_linters#dockerfile#hadolint#GetCommand'), \ 'command_callback': 'ale_linters#dockerfile#hadolint#GetCommand',
\ 'callback': 'ale_linters#dockerfile#hadolint#Handle', \ 'callback': 'ale_linters#dockerfile#hadolint#Handle',
\}) \})

View File

@@ -11,18 +11,10 @@ function! ale_linters#elixir#credo#Handle(buffer, lines) abort
let l:type = l:match[3] let l:type = l:match[3]
let l:text = l:match[4] let l:text = l:match[4]
" Refactoring opportunities if l:type is# 'C'
if l:type is# 'F' let l:type = 'E'
let l:type = 'W'
" Consistency
elseif l:type is# 'C'
let l:type = 'W'
" Software Design
elseif l:type is# 'D'
let l:type = 'I'
" Code Readability
elseif l:type is# 'R' elseif l:type is# 'R'
let l:type = 'I' let l:type = 'W'
endif endif
call add(l:output, { call add(l:output, {
@@ -37,27 +29,9 @@ function! ale_linters#elixir#credo#Handle(buffer, lines) abort
return l:output return l:output
endfunction endfunction
function! ale_linters#elixir#credo#GetMode() abort
if get(g:, 'ale_elixir_credo_strict', 0)
return '--strict'
else
return 'suggest'
endif
endfunction
function! ale_linters#elixir#credo#GetCommand(buffer) abort
let l:project_root = ale#handlers#elixir#FindMixProjectRoot(a:buffer)
let l:mode = ale_linters#elixir#credo#GetMode()
return ale#path#CdString(l:project_root)
\ . 'mix help credo && '
\ . 'mix credo ' . ale_linters#elixir#credo#GetMode()
\ . ' --format=flycheck --read-from-stdin %s'
endfunction
call ale#linter#Define('elixir', { call ale#linter#Define('elixir', {
\ 'name': 'credo', \ 'name': 'credo',
\ 'executable': 'mix', \ 'executable': 'mix',
\ 'command': function('ale_linters#elixir#credo#GetCommand'), \ 'command': 'mix help credo && mix credo suggest --format=flycheck --read-from-stdin %s',
\ 'callback': 'ale_linters#elixir#credo#Handle', \ 'callback': 'ale_linters#elixir#credo#Handle',
\}) \})

View File

@@ -25,17 +25,10 @@ function! ale_linters#elixir#dialyxir#Handle(buffer, lines) abort
return l:output return l:output
endfunction endfunction
function! ale_linters#elixir#dialyxir#GetCommand(buffer) abort
let l:project_root = ale#handlers#elixir#FindMixProjectRoot(a:buffer)
return ale#path#CdString(l:project_root)
\ . ' mix help dialyzer && mix dialyzer'
endfunction
call ale#linter#Define('elixir', { call ale#linter#Define('elixir', {
\ 'name': 'dialyxir', \ 'name': 'dialyxir',
\ 'executable': 'mix', \ 'executable': 'mix',
\ 'command': function('ale_linters#elixir#dialyxir#GetCommand'), \ 'command': 'mix dialyzer',
\ 'callback': 'ale_linters#elixir#dialyxir#Handle', \ 'callback': 'ale_linters#elixir#dialyxir#Handle',
\}) \})

View File

@@ -29,17 +29,10 @@ function! ale_linters#elixir#dogma#Handle(buffer, lines) abort
return l:output return l:output
endfunction endfunction
function! ale_linters#elixir#dogma#GetCommand(buffer) abort
let l:project_root = ale#handlers#elixir#FindMixProjectRoot(a:buffer)
return ale#path#CdString(l:project_root)
\ . ' mix help dogma && mix dogma %s --format=flycheck'
endfunction
call ale#linter#Define('elixir', { call ale#linter#Define('elixir', {
\ 'name': 'dogma', \ 'name': 'dogma',
\ 'executable': 'mix', \ 'executable': 'mix',
\ 'command': function('ale_linters#elixir#dogma#GetCommand'), \ 'command': 'mix help dogma && mix dogma %s --format=flycheck',
\ 'lint_file': 1, \ 'lint_file': 1,
\ 'callback': 'ale_linters#elixir#dogma#Handle', \ 'callback': 'ale_linters#elixir#dogma#Handle',
\}) \})

View File

@@ -1,21 +0,0 @@
" Author: Jon Parise <jon@indelible.org>
" Description: ElixirLS integration (https://github.com/JakeBecker/elixir-ls)
call ale#Set('elixir_elixir_ls_release', 'elixir-ls')
call ale#Set('elixir_elixir_ls_config', {})
function! ale_linters#elixir#elixir_ls#GetExecutable(buffer) abort
let l:dir = ale#path#Simplify(ale#Var(a:buffer, 'elixir_elixir_ls_release'))
let l:cmd = has('win32') ? '\language_server.bat' : '/language_server.sh'
return l:dir . l:cmd
endfunction
call ale#linter#Define('elixir', {
\ 'name': 'elixir-ls',
\ 'lsp': 'stdio',
\ 'executable': function('ale_linters#elixir#elixir_ls#GetExecutable'),
\ 'command': function('ale_linters#elixir#elixir_ls#GetExecutable'),
\ 'project_root': function('ale#handlers#elixir#FindMixUmbrellaRoot'),
\ 'lsp_config': {b -> ale#Var(b, 'elixir_elixir_ls_config')},
\})

View File

@@ -1,52 +0,0 @@
" Author: evnu - https://github.com/evnu
" Author: colbydehart - https://github.com/colbydehart
" Description: Mix compile checking for Elixir files
function! ale_linters#elixir#mix#Handle(buffer, lines) abort
" Matches patterns like the following:
"
" Error format
" ** (CompileError) apps/sim/lib/sim/server.ex:87: undefined function update_in/4
"
" TODO: Warning format
" warning: variable "foobar" does not exist and is being expanded to "foobar()", please use parentheses to remove the ambiguity or change the variable name
let l:pattern = '\v\(([^\)]+Error)\) ([^:]+):([^:]+): (.+)$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:type = 'E'
let l:text = l:match[4]
call add(l:output, {
\ 'bufnr': a:buffer,
\ 'lnum': l:match[3] + 0,
\ 'col': 0,
\ 'type': l:type,
\ 'text': l:text,
\})
endfor
return l:output
endfunction
function! ale_linters#elixir#mix#GetCommand(buffer) abort
let l:project_root = ale#handlers#elixir#FindMixProjectRoot(a:buffer)
let l:temp_dir = ale#command#CreateDirectory(a:buffer)
let l:mix_build_path = has('win32')
\ ? 'set MIX_BUILD_PATH=' . ale#Escape(l:temp_dir) . ' &&'
\ : 'MIX_BUILD_PATH=' . ale#Escape(l:temp_dir)
return ale#path#CdString(l:project_root)
\ . l:mix_build_path
\ . ' mix compile %s'
endfunction
call ale#linter#Define('elixir', {
\ 'name': 'mix',
\ 'executable': 'mix',
\ 'command': function('ale_linters#elixir#mix#GetCommand'),
\ 'callback': 'ale_linters#elixir#mix#Handle',
\ 'lint_file': 1,
\})

View File

@@ -1,40 +0,0 @@
" Author: antew - https://github.com/antew
" Description: elm-language-server integration for elm (diagnostics, formatting, and more)
call ale#Set('elm_ls_executable', 'elm-language-server')
call ale#Set('elm_ls_use_global', get(g:, 'ale_use_global_executables', 1))
" elm-language-server will search for local and global binaries, if empty
call ale#Set('elm_ls_elm_path', '')
call ale#Set('elm_ls_elm_format_path', '')
call ale#Set('elm_ls_elm_test_path', '')
call ale#Set('elm_ls_elm_analyse_trigger', 'change')
function! elm_ls#GetRootDir(buffer) abort
let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm.json')
return !empty(l:elm_json) ? fnamemodify(l:elm_json, ':p:h') : ''
endfunction
function! elm_ls#GetOptions(buffer) abort
return {
\ 'elmPath': ale#Var(a:buffer, 'elm_ls_elm_path'),
\ 'elmFormatPath': ale#Var(a:buffer, 'elm_ls_elm_format_path'),
\ 'elmTestPath': ale#Var(a:buffer, 'elm_ls_elm_test_path'),
\ 'elmAnalyseTrigger': ale#Var(a:buffer, 'elm_ls_elm_analyse_trigger'),
\}
endfunction
call ale#linter#Define('elm', {
\ 'name': 'elm_ls',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#node#FindExecutable(b, 'elm_ls', [
\ 'node_modules/.bin/elm-language-server',
\ 'node_modules/.bin/elm-lsp',
\ 'elm-lsp'
\ ])},
\ 'command': '%e --stdio',
\ 'project_root': function('elm_ls#GetRootDir'),
\ 'language': 'elm',
\ 'initialization_options': function('elm_ls#GetOptions')
\})

View File

@@ -1,20 +1,45 @@
" Author: buffalocoder - https://github.com/buffalocoder, soywod - https://github.com/soywod, hecrj - https://github.com/hecrj " Author: buffalocoder - https://github.com/buffalocoder, soywod - https://github.com/soywod
" Description: Elm linting in Ale. Closely follows the Syntastic checker in https://github.com/ElmCast/elm-vim. " Description: Elm linting in Ale. Closely follows the Syntastic checker in https://github.com/ElmCast/elm-vim.
call ale#Set('elm_make_executable', 'elm') call ale#Set('elm_make_executable', 'elm-make')
call ale#Set('elm_make_use_global', get(g:, 'ale_use_global_executables', 0)) call ale#Set('elm_make_use_global', 0)
function! ale_linters#elm#make#GetExecutable(buffer) abort
return ale#node#FindExecutable(a:buffer, 'elm_make', [
\ 'node_modules/.bin/elm-make',
\])
endfunction
function! ale_linters#elm#make#Handle(buffer, lines) abort function! ale_linters#elm#make#Handle(buffer, lines) abort
let l:output = [] let l:output = []
let l:is_windows = has('win32')
let l:temp_dir = l:is_windows ? $TMP : $TMPDIR
let l:unparsed_lines = [] 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] is# '['
" Elm 0.19 let l:errors = json_decode(l:line)
call ale_linters#elm#make#HandleElm019Line(l:line, l:output)
elseif l:line[0] is# '[' for l:error in l:errors
" Elm 0.18 " Check if file is from the temp directory.
call ale_linters#elm#make#HandleElm018Line(l:line, l:output) " Filters out any errors not related to the buffer.
if l:is_windows
let l:file_is_buffer = l:error.file[0:len(l:temp_dir) - 1] is? l:temp_dir
else
let l:file_is_buffer = l:error.file[0:len(l:temp_dir) - 1] is# l:temp_dir
endif
if l:file_is_buffer
call add(l:output, {
\ 'lnum': l:error.region.start.line,
\ 'col': l:error.region.start.column,
\ 'end_lnum': l:error.region.end.line,
\ 'end_col': l:error.region.end.column,
\ 'type': (l:error.type is? 'error') ? 'E' : 'W',
\ 'text': l:error.overview,
\ 'detail': l:error.overview . "\n\n" . l:error.details
\})
endif
endfor
elseif l:line isnot# 'Successfully generated /dev/null' elseif l:line isnot# 'Successfully generated /dev/null'
call add(l:unparsed_lines, l:line) call add(l:unparsed_lines, l:line)
endif endif
@@ -32,209 +57,33 @@ function! ale_linters#elm#make#Handle(buffer, lines) abort
return l:output return l:output
endfunction endfunction
function! ale_linters#elm#make#HandleElm019Line(line, output) abort
let l:report = json_decode(a:line)
if l:report.type is? 'error'
" General problem
let l:details = ale_linters#elm#make#ParseMessage(l:report.message)
if empty(l:report.path)
let l:report.path = 'Elm'
endif
if ale_linters#elm#make#FileIsBuffer(l:report.path)
call add(a:output, {
\ 'lnum': 1,
\ 'type': 'E',
\ 'text': l:details,
\})
else
call add(a:output, {
\ 'lnum': 1,
\ 'type': 'E',
\ 'text': l:report.path .' - '. l:details,
\ 'detail': l:report.path ." ----------\n\n". l:details,
\})
endif
else
" Compilation errors
for l:error in l:report.errors
let l:file_is_buffer = ale_linters#elm#make#FileIsBuffer(l:error.path)
for l:problem in l:error.problems
let l:details = ale_linters#elm#make#ParseMessage(l:problem.message)
if l:file_is_buffer
" Buffer module has problems
call add(a:output, {
\ 'lnum': l:problem.region.start.line,
\ 'col': l:problem.region.start.column,
\ 'end_lnum': l:problem.region.end.line,
\ 'end_col': l:problem.region.end.column,
\ 'type': 'E',
\ 'text': l:details,
\})
else
" Imported module has problems
let l:location = l:error.path .':'. l:problem.region.start.line
call add(a:output, {
\ 'lnum': 1,
\ 'type': 'E',
\ 'text': l:location .' - '. l:details,
\ 'detail': l:location ." ----------\n\n". l:details,
\})
endif
endfor
endfor
endif
endfunction
function! ale_linters#elm#make#HandleElm018Line(line, output) abort
let l:errors = json_decode(a:line)
for l:error in l:errors
let l:file_is_buffer = ale_linters#elm#make#FileIsBuffer(l:error.file)
if l:file_is_buffer
" Current buffer has problems
call add(a:output, {
\ 'lnum': l:error.region.start.line,
\ 'col': l:error.region.start.column,
\ 'end_lnum': l:error.region.end.line,
\ 'end_col': l:error.region.end.column,
\ 'type': (l:error.type is? 'error') ? 'E' : 'W',
\ 'text': l:error.overview,
\ 'detail': l:error.overview . "\n\n" . l:error.details
\})
elseif l:error.type is? 'error'
" Imported module has errors
let l:location = l:error.file .':'. l:error.region.start.line
call add(a:output, {
\ 'lnum': 1,
\ 'type': 'E',
\ 'text': l:location .' - '. l:error.overview,
\ 'detail': l:location ." ----------\n\n". l:error.overview . "\n\n" . l:error.details
\})
endif
endfor
endfunction
function! ale_linters#elm#make#FileIsBuffer(path) abort
return ale#path#IsTempName(a:path)
endfunction
function! ale_linters#elm#make#ParseMessage(message) abort
return join(map(copy(a:message), 'ale_linters#elm#make#ParseMessageItem(v:val)'), '')
endfunction
function! ale_linters#elm#make#ParseMessageItem(item) abort
if type(a:item) is v:t_string
return a:item
else
return a:item.string
endif
endfunction
function! ale_linters#elm#make#GetPackageFile(buffer) abort
let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm.json')
if empty(l:elm_json)
" Fallback to Elm 0.18
let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm-package.json')
endif
return l:elm_json
endfunction
function! ale_linters#elm#make#IsVersionGte19(buffer) abort
let l:elm_json = ale_linters#elm#make#GetPackageFile(a:buffer)
if l:elm_json =~# '-package'
return 0
else
return 1
endif
endfunction
function! ale_linters#elm#make#GetRootDir(buffer) abort
let l:elm_json = ale_linters#elm#make#GetPackageFile(a:buffer)
if empty(l:elm_json)
return ''
else
return fnamemodify(l:elm_json, ':p:h')
endif
endfunction
function! ale_linters#elm#make#IsTest(buffer) abort
let l:root_dir = ale_linters#elm#make#GetRootDir(a:buffer)
if empty(l:root_dir)
return 0
endif
let l:tests_dir = join([l:root_dir, 'tests', ''], has('win32') ? '\' : '/')
let l:buffer_path = fnamemodify(bufname(a:buffer), ':p')
if stridx(l:buffer_path, l:tests_dir) == 0
return 1
else
return 0
endif
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:executable = ale_linters#elm#make#GetExecutable(a:buffer) let l:elm_package = ale#path#FindNearestFile(a:buffer, 'elm-package.json')
let l:root_dir = ale_linters#elm#make#GetRootDir(a:buffer) let l:elm_exe = ale_linters#elm#make#GetExecutable(a:buffer)
let l:is_v19 = ale_linters#elm#make#IsVersionGte19(a:buffer) if empty(l:elm_package)
let l:is_using_elm_test = l:executable =~# 'elm-test$'
if empty(l:root_dir)
let l:dir_set_cmd = '' let l:dir_set_cmd = ''
else else
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 ' . ale#Escape(l:root_dir) . ' && '
endif endif
" elm-test needs to know the path of elm-make if elm isn't installed globally. " The elm-make compiler, at the time of this writing, uses '/dev/null' as
" https://github.com/rtfeldman/node-test-runner/blob/57728f10668f2d2ab3179e7e3208bcfa9a1f19aa/README.md#--compiler
if l:is_v19 && l:is_using_elm_test
let l:elm_make_executable = ale#node#FindExecutable(a:buffer, 'elm_make', ['node_modules/.bin/elm'])
let l:elm_test_compiler_flag = ' --compiler ' . l:elm_make_executable . ' '
else
let l:elm_test_compiler_flag = ' '
endif
" The elm 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. It does not use NUL on Windows.
" Source: https://github.com/elm-lang/elm-compiler/blob/19d5a769b30ec0b2fc4475985abb4cd94cd1d6c3/builder/src/Generate/Output.hs#L253 " Source: https://github.com/elm-lang/elm-make/blob/master/src/Flags.hs
return l:dir_set_cmd . '%e make --report=json --output=/dev/null' . l:elm_test_compiler_flag . '%t' let l:elm_cmd = ale#Escape(l:elm_exe)
endfunction \ . ' --report=json'
\ . ' --output=/dev/null'
function! ale_linters#elm#make#GetExecutable(buffer) abort return l:dir_set_cmd . ' ' . l:elm_cmd . ' %t'
let l:is_test = ale_linters#elm#make#IsTest(a:buffer)
let l:is_v19 = ale_linters#elm#make#IsVersionGte19(a:buffer)
if l:is_test && l:is_v19
return ale#node#FindExecutable(
\ a:buffer,
\ 'elm_make',
\ ['node_modules/.bin/elm-test', 'node_modules/.bin/elm']
\)
else
return ale#node#FindExecutable(a:buffer, 'elm_make', ['node_modules/.bin/elm'])
endif
endfunction endfunction
call ale#linter#Define('elm', { call ale#linter#Define('elm', {
\ 'name': 'make', \ 'name': 'make',
\ 'executable': function('ale_linters#elm#make#GetExecutable'), \ 'executable_callback': 'ale_linters#elm#make#GetExecutable',
\ 'output_stream': 'both', \ 'output_stream': 'both',
\ 'command': function('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

@@ -1,93 +0,0 @@
" Author: Autoine Gagne - https://github.com/AntoineGagne
" Description: Define a checker that runs dialyzer on Erlang files.
let g:ale_erlang_dialyzer_executable =
\ get(g:, 'ale_erlang_dialyzer_executable', 'dialyzer')
let g:ale_erlang_dialyzer_plt_file =
\ get(g:, 'ale_erlang_dialyzer_plt_file', '')
let g:ale_erlang_dialyzer_rebar3_profile =
\ get(g:, 'ale_erlang_dialyzer_rebar3_profile', 'default')
function! ale_linters#erlang#dialyzer#GetRebar3Profile(buffer) abort
return ale#Var(a:buffer, 'erlang_dialyzer_rebar3_profile')
endfunction
function! ale_linters#erlang#dialyzer#FindPlt(buffer) abort
let l:plt_file = ''
let l:rebar3_profile = ale_linters#erlang#dialyzer#GetRebar3Profile(a:buffer)
let l:plt_file_directory = ale#path#FindNearestDirectory(a:buffer, '_build/' . l:rebar3_profile)
if !empty(l:plt_file_directory)
let l:plt_file = globpath(l:plt_file_directory, '*_plt', 0, 1)
endif
if !empty(l:plt_file)
return l:plt_file[0]
endif
if !empty($REBAR_PLT_DIR)
return expand('$REBAR_PLT_DIR/dialyzer/plt')
endif
return expand('$HOME/.dialyzer_plt')
endfunction
function! ale_linters#erlang#dialyzer#GetPlt(buffer) abort
let l:plt_file = ale#Var(a:buffer, 'erlang_dialyzer_plt_file')
if !empty(l:plt_file)
return l:plt_file
endif
return ale_linters#erlang#dialyzer#FindPlt(a:buffer)
endfunction
function! ale_linters#erlang#dialyzer#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'erlang_dialyzer_executable')
endfunction
function! ale_linters#erlang#dialyzer#GetCommand(buffer) abort
let l:command = ale#Escape(ale_linters#erlang#dialyzer#GetExecutable(a:buffer))
\ . ' -n'
\ . ' --plt ' . ale#Escape(ale_linters#erlang#dialyzer#GetPlt(a:buffer))
\ . ' -Wunmatched_returns'
\ . ' -Werror_handling'
\ . ' -Wrace_conditions'
\ . ' -Wunderspecs'
\ . ' %s'
return l:command
endfunction
function! ale_linters#erlang#dialyzer#Handle(buffer, lines) abort
" Match patterns like the following:
"
" erl_tidy_prv_fmt.erl:3: Callback info about the provider behaviour is not available
let l:pattern = '^\S\+:\(\d\+\): \(.\+\)$'
let l:output = []
for l:line in a:lines
let l:match = matchlist(l:line, l:pattern)
if len(l:match) != 0
let l:code = l:match[2]
call add(l:output, {
\ 'lnum': str2nr(l:match[1]),
\ 'lcol': 0,
\ 'text': l:code,
\ 'type': 'W'
\})
endif
endfor
return l:output
endfunction
call ale#linter#Define('erlang', {
\ 'name': 'dialyzer',
\ 'executable': function('ale_linters#erlang#dialyzer#GetExecutable'),
\ 'command': function('ale_linters#erlang#dialyzer#GetCommand'),
\ 'callback': function('ale_linters#erlang#dialyzer#Handle'),
\ 'lint_file': 1
\})

View File

@@ -3,8 +3,8 @@
let g:ale_erlang_erlc_options = get(g:, 'ale_erlang_erlc_options', '') 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 = ale#util#Tempname() let l:output_file = tempname()
call ale#command#ManageFile(a:buffer, l:output_file) call ale#engine#ManageFile(a:buffer, l:output_file)
return 'erlc -o ' . ale#Escape(l:output_file) return 'erlc -o ' . ale#Escape(l:output_file)
\ . ' ' . ale#Var(a:buffer, 'erlang_erlc_options') \ . ' ' . ale#Var(a:buffer, 'erlang_erlc_options')
@@ -91,6 +91,6 @@ endfunction
call ale#linter#Define('erlang', { call ale#linter#Define('erlang', {
\ 'name': 'erlc', \ 'name': 'erlc',
\ 'executable': 'erlc', \ 'executable': 'erlc',
\ 'command': function('ale_linters#erlang#erlc#GetCommand'), \ 'command_callback': 'ale_linters#erlang#erlc#GetCommand',
\ 'callback': 'ale_linters#erlang#erlc#Handle', \ 'callback': 'ale_linters#erlang#erlc#Handle',
\}) \})

View File

@@ -3,22 +3,24 @@
call ale#Set('erlang_syntaxerl_executable', 'syntaxerl') call ale#Set('erlang_syntaxerl_executable', 'syntaxerl')
function! ale_linters#erlang#syntaxerl#RunHelpCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'erlang_syntaxerl_executable')
return ale#command#Run( function! ale_linters#erlang#syntaxerl#GetExecutable(buffer) abort
\ a:buffer, return ale#Var(a:buffer, 'erlang_syntaxerl_executable')
\ ale#Escape(l:executable) . ' -h',
\ function('ale_linters#erlang#syntaxerl#GetCommand'),
\)
endfunction endfunction
function! ale_linters#erlang#syntaxerl#GetCommand(buffer, output, meta) abort
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 let l:use_b_option = match(a:output, '\C\V-b, --base\>') > -1
return '%e' . (l:use_b_option ? ' -b %s %t' : ' %t') return s:GetEscapedExecutable(a:buffer) . (l:use_b_option ? ' -b %s %t' : ' %t')
endfunction endfunction
function! ale_linters#erlang#syntaxerl#Handle(buffer, lines) abort function! ale_linters#erlang#syntaxerl#Handle(buffer, lines) abort
let l:pattern = '\v\C:(\d+):( warning:)? (.+)' let l:pattern = '\v\C:(\d+):( warning:)? (.+)'
let l:loclist = [] let l:loclist = []
@@ -34,9 +36,18 @@ function! ale_linters#erlang#syntaxerl#Handle(buffer, lines) abort
return l:loclist return l:loclist
endfunction endfunction
function! s:GetEscapedExecutable(buffer) abort
return ale#Escape(ale_linters#erlang#syntaxerl#GetExecutable(a:buffer))
endfunction
call ale#linter#Define('erlang', { call ale#linter#Define('erlang', {
\ 'name': 'syntaxerl', \ 'name': 'syntaxerl',
\ 'executable': {b -> ale#Var(b, 'erlang_syntaxerl_executable')}, \ 'executable_callback': 'ale_linters#erlang#syntaxerl#GetExecutable',
\ 'command': {b -> ale_linters#erlang#syntaxerl#RunHelpCommand(b)}, \ 'command_chain': [
\ {'callback': 'ale_linters#erlang#syntaxerl#FeatureCheck'},
\ {'callback': 'ale_linters#erlang#syntaxerl#GetCommand'},
\ ],
\ 'callback': 'ale_linters#erlang#syntaxerl#Handle', \ 'callback': 'ale_linters#erlang#syntaxerl#Handle',
\}) \})

View File

@@ -19,7 +19,7 @@ call ale#linter#Define('eruby', {
\ 'aliases': ['erubylint'], \ 'aliases': ['erubylint'],
\ 'executable': 'erb', \ 'executable': 'erb',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'command': function('ale_linters#eruby#erb#GetCommand'), \ 'command_callback': 'ale_linters#eruby#erb#GetCommand',
\ 'callback': 'ale#handlers#ruby#HandleSyntaxErrors', \ 'callback': 'ale#handlers#ruby#HandleSyntaxErrors',
\}) \})

View File

@@ -1,10 +1,14 @@
" Author: Eddie Lebow https://github.com/elebow " Author: Eddie Lebow https://github.com/elebow
" Description: eruby checker using `erubi` " Description: eruby checker using `erubi`
function! ale_linters#eruby#erubi#GetCommand(buffer, output, meta) abort function! ale_linters#eruby#erubi#CheckErubi(buffer) abort
return 'ruby -r erubi/capture_end -e ' . ale#Escape('""')
endfunction
function! ale_linters#eruby#erubi#GetCommand(buffer, check_erubi_output) abort
let l:rails_root = ale#ruby#FindRailsRoot(a:buffer) let l:rails_root = ale#ruby#FindRailsRoot(a:buffer)
if !empty(a:output) if (!empty(a:check_erubi_output))
" The empty command in CheckErubi returns nothing if erubi runs and " The empty command in CheckErubi returns nothing if erubi runs and
" emits an error if erubi is not present " emits an error if erubi is not present
return '' return ''
@@ -23,10 +27,9 @@ endfunction
call ale#linter#Define('eruby', { call ale#linter#Define('eruby', {
\ 'name': 'erubi', \ 'name': 'erubi',
\ 'executable': 'ruby', \ 'executable': 'ruby',
\ 'command': {buffer -> ale#command#Run( \ 'command_chain': [
\ buffer, \ {'callback': 'ale_linters#eruby#erubi#CheckErubi'},
\ 'ruby -r erubi/capture_end -e ' . ale#Escape('""'), \ {'callback': 'ale_linters#eruby#erubi#GetCommand', 'output_stream': 'stderr'},
\ function('ale_linters#eruby#erubi#GetCommand'), \ ],
\ )},
\ 'callback': 'ale#handlers#ruby#HandleSyntaxErrors', \ 'callback': 'ale#handlers#ruby#HandleSyntaxErrors',
\}) \})

View File

@@ -18,6 +18,6 @@ call ale#linter#Define('eruby', {
\ 'name': 'erubis', \ 'name': 'erubis',
\ 'executable': 'erubis', \ 'executable': 'erubis',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'command': function('ale_linters#eruby#erubis#GetCommand'), \ 'command_callback': 'ale_linters#eruby#erubis#GetCommand',
\ 'callback': 'ale#handlers#ruby#HandleSyntaxErrors', \ 'callback': 'ale#handlers#ruby#HandleSyntaxErrors',
\}) \})

View File

@@ -1,62 +0,0 @@
" Author: aclemons - https://github.com/aclemons
" based on the ale rubocop linter
" Description: Ruumba, RuboCop linting for ERB templates.
call ale#Set('eruby_ruumba_executable', 'ruumba')
call ale#Set('eruby_ruumba_options', '')
function! ale_linters#eruby#ruumba#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'eruby_ruumba_executable')
return ale#ruby#EscapeExecutable(l:executable, 'ruumba')
\ . ' --format json --force-exclusion '
\ . ale#Var(a:buffer, 'eruby_ruumba_options')
\ . ' --stdin ' . ale#Escape(expand('#' . a:buffer . ':p'))
endfunction
function! ale_linters#eruby#ruumba#Handle(buffer, lines) abort
try
let l:errors = json_decode(a:lines[0])
catch
return []
endtry
if !has_key(l:errors, 'summary')
\|| l:errors['summary']['offense_count'] == 0
\|| empty(l:errors['files'])
return []
endif
let l:output = []
for l:error in l:errors['files'][0]['offenses']
let l:start_col = l:error['location']['column'] + 0
call add(l:output, {
\ 'lnum': l:error['location']['line'] + 0,
\ 'col': l:start_col,
\ 'end_col': l:start_col + l:error['location']['length'] - 1,
\ 'code': l:error['cop_name'],
\ 'text': l:error['message'],
\ 'type': ale_linters#eruby#ruumba#GetType(l:error['severity']),
\})
endfor
return l:output
endfunction
function! ale_linters#eruby#ruumba#GetType(severity) abort
if a:severity is? 'convention'
\|| a:severity is? 'warning'
\|| a:severity is? 'refactor'
return 'W'
endif
return 'E'
endfunction
call ale#linter#Define('eruby', {
\ 'name': 'ruumba',
\ 'executable': {b -> ale#Var(b, 'eruby_ruumba_executable')},
\ 'command': function('ale_linters#eruby#ruumba#GetCommand'),
\ 'callback': 'ale_linters#eruby#ruumba#Handle',
\})

View File

@@ -2,10 +2,18 @@
" Description: gcc for Fortran files " Description: gcc for Fortran files
" This option can be set to 0 to use -ffixed-form " This option can be set to 0 to use -ffixed-form
call ale#Set('fortran_gcc_use_free_form', 1) if !exists('g:ale_fortran_gcc_use_free_form')
call ale#Set('fortran_gcc_executable', 'gcc') 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.
call ale#Set('fortran_gcc_options', '-Wall') if !exists('g:ale_fortran_gcc_options')
let g:ale_fortran_gcc_options = '-Wall'
endif
function! ale_linters#fortran#gcc#Handle(buffer, lines) abort function! ale_linters#fortran#gcc#Handle(buffer, lines) abort
" We have to match a starting line and a later ending line together, " We have to match a starting line and a later ending line together,
@@ -53,20 +61,26 @@ 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 function! ale_linters#fortran#gcc#GetCommand(buffer) abort
let l:layout_option = ale#Var(a:buffer, 'fortran_gcc_use_free_form') let l:layout_option = ale#Var(a:buffer, 'fortran_gcc_use_free_form')
\ ? '-ffree-form' \ ? '-ffree-form'
\ : '-ffixed-form' \ : '-ffixed-form'
return '%e -S -x f95 -fsyntax-only ' . l:layout_option return ale_linters#fortran#gcc#GetExecutable(a:buffer)
\ . ale#Pad(ale#Var(a:buffer, 'fortran_gcc_options')) \ . ' -S -x f95 -fsyntax-only '
\ . ' -' \ . l:layout_option . ' '
\ . ale#Var(a:buffer, 'fortran_gcc_options') . ' '
\ . '-'
endfunction endfunction
call ale#linter#Define('fortran', { call ale#linter#Define('fortran', {
\ 'name': 'gcc', \ 'name': 'gcc',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': {b -> ale#Var(b, 'fortran_gcc_executable')}, \ 'executable_callback': 'ale_linters#fortran#gcc#GetExecutable',
\ 'command': function('ale_linters#fortran#gcc#GetCommand'), \ 'command_callback': 'ale_linters#fortran#gcc#GetCommand',
\ 'callback': 'ale_linters#fortran#gcc#Handle', \ 'callback': 'ale_linters#fortran#gcc#Handle',
\}) \})

View File

@@ -1,19 +0,0 @@
" Author: unpairedbracket ben.spiers22@gmail.com
" Description: A language server for fortran
call ale#Set('fortran_language_server_executable', 'fortls')
call ale#Set('fortran_language_server_use_global', get(g:, 'ale_use_global_executables', 0))
function! ale_linters#fortran#language_server#GetProjectRoot(buffer) abort
let l:fortls_file = ale#path#FindNearestFile(a:buffer, '.fortls')
return !empty(l:fortls_file) ? fnamemodify(l:fortls_file, ':h') : ''
endfunction
call ale#linter#Define('fortran', {
\ 'name': 'language_server',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'fortran_language_server_executable')},
\ 'command': '%e',
\ 'project_root': function('ale_linters#fortran#language_server#GetProjectRoot'),
\})

View File

@@ -1,11 +1,19 @@
" Author: RyanSquared <vandor2012@gmail.com> " Author: RyanSquared <vandor2012@gmail.com>
" Description: `fusion-lint` linter for FusionScript files " Description: `fusion-lint` linter for FusionScript files
call ale#Set('fuse_fusionlint_executable', 'fusion-lint') let g:ale_fuse_fusionlint_executable =
call ale#Set('fuse_fusionlint_options', '') \ 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 function! ale_linters#fuse#fusionlint#GetCommand(buffer) abort
return '%e' . ale#Pad(ale#Var(a:buffer, 'fuse_fusionlint_options')) return ale#Escape(ale_linters#fuse#fusionlint#GetExecutable(a:buffer))
\ . ' ' . ale#Var(a:buffer, 'fuse_fusionlint_options')
\ . ' --filename %s -i' \ . ' --filename %s -i'
endfunction endfunction
@@ -27,7 +35,7 @@ endfunction
call ale#linter#Define('fuse', { call ale#linter#Define('fuse', {
\ 'name': 'fusionlint', \ 'name': 'fusionlint',
\ 'executable': {b -> ale#Var(b, 'fuse_fusionlint_executable')}, \ 'executable_callback': 'ale_linters#fuse#fusionlint#GetExecutable',
\ 'command': function('ale_linters#fuse#fusionlint#GetCommand'), \ 'command_callback': 'ale_linters#fuse#fusionlint#GetCommand',
\ 'callback': 'ale_linters#fuse#fusionlint#Handle', \ 'callback': 'ale_linters#fuse#fusionlint#Handle',
\}) \})

View File

@@ -1,9 +1,11 @@
" Author: Nick Yamane <nick.diego@gmail.com> " Author: Nick Yamane <nick.diego@gmail.com>
" Description: gitlint for git commit message files " Description: gitlint for git commit message files
call ale#Set('gitcommit_gitlint_executable', 'gitlint') let g:ale_gitcommit_gitlint_executable =
call ale#Set('gitcommit_gitlint_options', '') \ get(g:, 'ale_gitcommit_gitlint_executable', 'gitlint')
call ale#Set('gitcommit_gitlint_use_global', get(g:, 'ale_use_global_executables', 0)) let g:ale_gitcommit_gitlint_options = get(g:, 'ale_gitcommit_gitlint_options', '')
let g:ale_gitcommit_gitlint_use_global = get(g:, 'ale_gitcommit_gitlint_use_global', 0)
function! ale_linters#gitcommit#gitlint#GetExecutable(buffer) abort function! ale_linters#gitcommit#gitlint#GetExecutable(buffer) abort
return ale#python#FindExecutable(a:buffer, 'gitcommit_gitlint', ['gitlint']) return ale#python#FindExecutable(a:buffer, 'gitcommit_gitlint', ['gitlint'])
@@ -11,10 +13,13 @@ endfunction
function! ale_linters#gitcommit#gitlint#GetCommand(buffer) abort function! ale_linters#gitcommit#gitlint#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'gitcommit_gitlint_options') let l:options = ale#Var(a:buffer, 'gitcommit_gitlint_options')
let l:executable = ale_linters#gitcommit#gitlint#GetExecutable(a:buffer)
return '%e' . ale#Pad(l:options) . ' lint' return ale#Escape(l:executable)
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' lint'
endfunction endfunction
function! ale_linters#gitcommit#gitlint#Handle(buffer, lines) abort function! ale_linters#gitcommit#gitlint#Handle(buffer, lines) abort
" Matches patterns line the following: " Matches patterns line the following:
let l:pattern = '\v^(\d+): (\w+) (.*)$' let l:pattern = '\v^(\d+): (\w+) (.*)$'
@@ -23,12 +28,6 @@ function! ale_linters#gitcommit#gitlint#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern) for l:match in ale#util#GetMatches(a:lines, l:pattern)
let l:code = l:match[2] let l:code = l:match[2]
if !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
if l:code is# 'T2' || l:code is# 'B2'
continue
endif
endif
let l:item = { let l:item = {
\ 'lnum': l:match[1] + 0, \ 'lnum': l:match[1] + 0,
\ 'text': l:match[3], \ 'text': l:match[3],
@@ -42,10 +41,12 @@ function! ale_linters#gitcommit#gitlint#Handle(buffer, lines) abort
return l:output return l:output
endfunction endfunction
call ale#linter#Define('gitcommit', { call ale#linter#Define('gitcommit', {
\ 'name': 'gitlint', \ 'name': 'gitlint',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': function('ale_linters#gitcommit#gitlint#GetExecutable'), \ 'executable_callback': 'ale_linters#gitcommit#gitlint#GetExecutable',
\ 'command': function('ale_linters#gitcommit#gitlint#GetCommand'), \ 'command_callback': 'ale_linters#gitcommit#gitlint#GetCommand',
\ 'callback': 'ale_linters#gitcommit#gitlint#Handle', \ 'callback': 'ale_linters#gitcommit#gitlint#Handle',
\}) \})

View File

@@ -4,13 +4,19 @@
" TODO: Once https://github.com/KhronosGroup/glslang/pull/1047 is accepted, " TODO: Once https://github.com/KhronosGroup/glslang/pull/1047 is accepted,
" we can use stdin. " we can use stdin.
call ale#Set('glsl_glslang_executable', 'glslangValidator') let g:ale_glsl_glslang_executable =
call ale#Set('glsl_glslang_options', '') \ get(g:, 'ale_glsl_glslang_executable', 'glslangValidator')
let g:ale_glsl_glslang_options = get(g:, 'ale_glsl_glslang_options', '')
function! ale_linters#glsl#glslang#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'glsl_glslang_executable')
endfunction
function! ale_linters#glsl#glslang#GetCommand(buffer) abort function! ale_linters#glsl#glslang#GetCommand(buffer) abort
return '%e' return ale_linters#glsl#glslang#GetExecutable(a:buffer)
\ . ale#Pad(ale#Var(a:buffer, 'glsl_glslang_options')) \ . ' ' . ale#Var(a:buffer, 'glsl_glslang_options')
\ . ' -C %t' \ . ' ' . '-C %t'
endfunction endfunction
function! ale_linters#glsl#glslang#Handle(buffer, lines) abort function! ale_linters#glsl#glslang#Handle(buffer, lines) abort
@@ -34,7 +40,7 @@ endfunction
call ale#linter#Define('glsl', { call ale#linter#Define('glsl', {
\ 'name': 'glslang', \ 'name': 'glslang',
\ 'executable': {b -> ale#Var(b, 'glsl_glslang_executable')}, \ 'executable_callback': 'ale_linters#glsl#glslang#GetExecutable',
\ 'command': function('ale_linters#glsl#glslang#GetCommand'), \ 'command_callback': 'ale_linters#glsl#glslang#GetCommand',
\ 'callback': 'ale_linters#glsl#glslang#Handle', \ 'callback': 'ale_linters#glsl#glslang#Handle',
\}) \})

View File

@@ -4,15 +4,22 @@
call ale#Set('glsl_glslls_executable', 'glslls') call ale#Set('glsl_glslls_executable', 'glslls')
call ale#Set('glsl_glslls_logfile', '') call ale#Set('glsl_glslls_logfile', '')
function! ale_linters#glsl#glslls#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'glsl_glslls_executable')
endfunction
function! ale_linters#glsl#glslls#GetCommand(buffer) abort function! ale_linters#glsl#glslls#GetCommand(buffer) abort
let l:executable = ale_linters#glsl#glslls#GetExecutable(a:buffer)
let l:logfile = ale#Var(a:buffer, 'glsl_glslls_logfile') let l:logfile = ale#Var(a:buffer, 'glsl_glslls_logfile')
let l:logfile_args = '' let l:logfile_args = ''
if l:logfile isnot# '' if l:logfile isnot# ''
let l:logfile_args = ' --verbose -l ' . l:logfile let l:logfile_args = ' --verbose -l ' . l:logfile
endif endif
return ale#Escape(l:executable) . l:logfile_args . ' --stdin'
endfunction
return '%e' . l:logfile_args . ' --stdin' function! ale_linters#glsl#glslls#GetLanguage(buffer) abort
return 'glsl'
endfunction endfunction
function! ale_linters#glsl#glslls#GetProjectRoot(buffer) abort function! ale_linters#glsl#glslls#GetProjectRoot(buffer) abort
@@ -24,7 +31,8 @@ endfunction
call ale#linter#Define('glsl', { call ale#linter#Define('glsl', {
\ 'name': 'glslls', \ 'name': 'glslls',
\ 'lsp': 'stdio', \ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'glsl_glslls_executable')}, \ 'executable_callback': 'ale_linters#glsl#glslls#GetExecutable',
\ 'command': function('ale_linters#glsl#glslls#GetCommand'), \ 'command_callback': 'ale_linters#glsl#glslls#GetCommand',
\ 'project_root': function('ale_linters#glsl#glslls#GetProjectRoot'), \ 'language_callback': 'ale_linters#glsl#glslls#GetLanguage',
\ 'project_root_callback': 'ale_linters#glsl#glslls#GetProjectRoot',
\}) \})

View File

@@ -1,31 +0,0 @@
" Author: Jerko Steiner <https://github.com/jeremija>
" Description: https://github.com/saibing/bingo
call ale#Set('go_bingo_executable', 'bingo')
call ale#Set('go_bingo_options', '--mode stdio')
function! ale_linters#go#bingo#GetCommand(buffer) abort
return ale#go#EnvString(a:buffer) . '%e' . ale#Pad(ale#Var(a:buffer, 'go_bingo_options'))
endfunction
function! ale_linters#go#bingo#FindProjectRoot(buffer) abort
let l:go_modules_off = ale#Var(a:buffer, 'go_go111module') is# 'off'
let l:project_root = l:go_modules_off ?
\ '' : ale#path#FindNearestFile(a:buffer, 'go.mod')
let l:mods = ':h'
if empty(l:project_root)
let l:project_root = ale#path#FindNearestDirectory(a:buffer, '.git')
let l:mods = ':h:h'
endif
return !empty(l:project_root) ? fnamemodify(l:project_root, l:mods) : ''
endfunction
call ale#linter#Define('go', {
\ 'name': 'bingo',
\ 'lsp': 'stdio',
\ 'executable': {b -> ale#Var(b, 'go_bingo_executable')},
\ 'command': function('ale_linters#go#bingo#GetCommand'),
\ 'project_root': function('ale_linters#go#bingo#FindProjectRoot'),
\})

View File

@@ -3,16 +3,38 @@
" 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>
call ale#Set('go_go_executable', 'go')
call ale#Set('go_gobuild_options', '') call ale#Set('go_gobuild_options', '')
function! ale_linters#go#gobuild#GetCommand(buffer) abort function! ale_linters#go#gobuild#ResetEnv() abort
unlet! s:go_env
endfunction
function! ale_linters#go#gobuild#GoEnv(buffer) abort
if exists('s:go_env')
return ''
endif
return 'go env GOPATH GOROOT'
endfunction
function! ale_linters#go#gobuild#GetCommand(buffer, goenv_output) abort
let l:options = ale#Var(a:buffer, 'go_gobuild_options') let l:options = ale#Var(a:buffer, 'go_gobuild_options')
if !exists('s:go_env')
let s:go_env = {
\ 'GOPATH': a:goenv_output[0],
\ 'GOROOT': a:goenv_output[1],
\}
endif
let l:gopath_env_command = has('win32')
\ ? 'set GOPATH=' . ale#Escape(s:go_env.GOPATH) . ' && '
\ : 'GOPATH=' . ale#Escape(s:go_env.GOPATH) . ' '
" Run go test in local directory with relative path " Run go test in local directory with relative path
return ale#path#BufferCdString(a:buffer) return l:gopath_env_command
\ . ale#go#EnvString(a:buffer) \ . ale#path#BufferCdString(a:buffer)
\ . ale#Var(a:buffer, 'go_go_executable') . ' test' \ . 'go test'
\ . (!empty(l:options) ? ' ' . l:options : '') \ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' -c -o /dev/null ./' \ . ' -c -o /dev/null ./'
endfunction endfunction
@@ -23,6 +45,7 @@ function! ale_linters#go#gobuild#GetMatches(lines) abort
" file.go:27: missing argument for Printf("%s"): format reads arg 2, have only 1 args " file.go:27: missing argument for Printf("%s"): format reads arg 2, have only 1 args
" 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: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" " file.go:5:2: expected declaration, found 'STRING' "log"
" go test returns relative paths so use tail of filename as part of pattern matcher " go test returns relative paths so use tail of filename as part of pattern matcher
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:? (.+)$' let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:? (.+)$'
@@ -47,11 +70,12 @@ function! ale_linters#go#gobuild#Handler(buffer, lines) abort
endfunction endfunction
call ale#linter#Define('go', { call ale#linter#Define('go', {
\ 'name': 'gobuild', \ 'name': 'go build',
\ 'aliases': ['go build'], \ 'executable': 'go',
\ 'executable': {b -> ale#Var(b, 'go_go_executable')}, \ 'command_chain': [
\ 'command': function('ale_linters#go#gobuild#GetCommand'), \ {'callback': 'ale_linters#go#gobuild#GoEnv', 'output_stream': 'stdout'},
\ '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, \ 'lint_file': 1,
\}) \})

View File

@@ -1,16 +1,10 @@
" Author: neersighted <bjorn@neersighted.com> " Author: neersighted <bjorn@neersighted.com>
" Description: gofmt for Go files " Description: gofmt for Go files
function! ale_linters#go#gofmt#GetCommand(buffer) abort
return ale#go#EnvString(a:buffer)
\ . '%e -e %t'
endfunction
call ale#linter#Define('go', { call ale#linter#Define('go', {
\ 'name': 'gofmt', \ 'name': 'gofmt',
\ 'output_stream': 'stderr', \ 'output_stream': 'stderr',
\ 'executable': 'gofmt', \ 'executable': 'gofmt',
\ 'command': function('ale_linters#go#gofmt#GetCommand'), \ 'command': 'gofmt -e %t',
\ 'callback': 'ale#handlers#unix#HandleAsError', \ 'callback': 'ale#handlers#unix#HandleAsError',
\}) \})

View File

@@ -1,59 +0,0 @@
" Author: Sascha Grunert <mail@saschagrunert.de>
" Description: Adds support of golangci-lint
call ale#Set('go_golangci_lint_options', '--enable-all')
call ale#Set('go_golangci_lint_executable', 'golangci-lint')
call ale#Set('go_golangci_lint_package', 0)
function! ale_linters#go#golangci_lint#GetCommand(buffer) abort
let l:filename = expand('#' . a:buffer . ':t')
let l:options = ale#Var(a:buffer, 'go_golangci_lint_options')
let l:lint_package = ale#Var(a:buffer, 'go_golangci_lint_package')
if l:lint_package
return ale#path#BufferCdString(a:buffer)
\ . ale#go#EnvString(a:buffer)
\ . '%e run '
\ . l:options
endif
return ale#path#BufferCdString(a:buffer)
\ . ale#go#EnvString(a:buffer)
\ . '%e run '
\ . ale#Escape(l:filename)
\ . ' ' . l:options
endfunction
function! ale_linters#go#golangci_lint#GetMatches(lines) abort
let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:?:?:?\s\*?(.+)$'
return ale#util#GetMatches(a:lines, l:pattern)
endfunction
function! ale_linters#go#golangci_lint#Handler(buffer, lines) abort
let l:dir = expand('#' . a:buffer . ':p:h')
let l:output = []
for l:match in ale_linters#go#golangci_lint#GetMatches(a:lines)
" l:match[1] will already be an absolute path, output from
" golangci_lint
call add(l:output, {
\ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]),
\ 'lnum': l:match[2] + 0,
\ 'col': l:match[3] + 0,
\ 'type': 'E',
\ 'text': l:match[4],
\})
endfor
return l:output
endfunction
call ale#linter#Define('go', {
\ 'name': 'golangci-lint',
\ 'executable': {b -> ale#Var(b, 'go_golangci_lint_executable')},
\ 'command': function('ale_linters#go#golangci_lint#GetCommand'),
\ 'callback': 'ale_linters#go#golangci_lint#Handler',
\ 'lint_file': 1,
\})

View File

@@ -1,21 +1,10 @@
" Author: neersighted <bjorn@neersighted.com> " Author: neersighted <bjorn@neersighted.com>
" Description: golint for Go files " Description: golint for Go files
call ale#Set('go_golint_executable', 'golint')
call ale#Set('go_golint_options', '')
function! ale_linters#go#golint#GetCommand(buffer) abort
let l:options = ale#Var(a:buffer, 'go_golint_options')
return ale#go#EnvString(a:buffer) . '%e'
\ . (!empty(l:options) ? ' ' . l:options : '')
\ . ' %t'
endfunction
call ale#linter#Define('go', { call ale#linter#Define('go', {
\ 'name': 'golint', \ 'name': 'golint',
\ 'output_stream': 'both', \ 'output_stream': 'both',
\ 'executable': {b -> ale#Var(b, 'go_golint_executable')}, \ 'executable': 'golint',
\ 'command': function('ale_linters#go#golint#GetCommand'), \ 'command': 'golint %t',
\ 'callback': 'ale#handlers#unix#HandleAsWarning', \ 'callback': 'ale#handlers#unix#HandleAsWarning',
\}) \})

View File

@@ -5,7 +5,12 @@ call ale#Set('go_gometalinter_options', '')
call ale#Set('go_gometalinter_executable', 'gometalinter') call ale#Set('go_gometalinter_executable', 'gometalinter')
call ale#Set('go_gometalinter_lint_package', 0) call ale#Set('go_gometalinter_lint_package', 0)
function! ale_linters#go#gometalinter#GetExecutable(buffer) abort
return ale#Var(a:buffer, 'go_gometalinter_executable')
endfunction
function! ale_linters#go#gometalinter#GetCommand(buffer) abort function! ale_linters#go#gometalinter#GetCommand(buffer) abort
let l:executable = ale_linters#go#gometalinter#GetExecutable(a:buffer)
let l:filename = expand('#' . a:buffer . ':t') let l:filename = expand('#' . a:buffer . ':t')
let l:options = ale#Var(a:buffer, 'go_gometalinter_options') let l:options = ale#Var(a:buffer, 'go_gometalinter_options')
let l:lint_package = ale#Var(a:buffer, 'go_gometalinter_lint_package') let l:lint_package = ale#Var(a:buffer, 'go_gometalinter_lint_package')
@@ -14,14 +19,12 @@ function! ale_linters#go#gometalinter#GetCommand(buffer) abort
" be calculated to absolute paths in the Handler " be calculated to absolute paths in the Handler
if l:lint_package if l:lint_package
return ale#path#BufferCdString(a:buffer) return ale#path#BufferCdString(a:buffer)
\ . ale#go#EnvString(a:buffer) \ . ale#Escape(l:executable)
\ . '%e'
\ . (!empty(l:options) ? ' ' . l:options : '') . ' .' \ . (!empty(l:options) ? ' ' . l:options : '') . ' .'
endif endif
return ale#path#BufferCdString(a:buffer) return ale#path#BufferCdString(a:buffer)
\ . ale#go#EnvString(a:buffer) \ . ale#Escape(l:executable)
\ . '%e'
\ . ' --include=' . ale#Escape(ale#util#EscapePCRE(l:filename)) \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(l:filename))
\ . (!empty(l:options) ? ' ' . l:options : '') . ' .' \ . (!empty(l:options) ? ' ' . l:options : '') . ' .'
endfunction endfunction
@@ -52,8 +55,8 @@ endfunction
call ale#linter#Define('go', { call ale#linter#Define('go', {
\ 'name': 'gometalinter', \ 'name': 'gometalinter',
\ 'executable': {b -> ale#Var(b, 'go_gometalinter_executable')}, \ 'executable_callback': 'ale_linters#go#gometalinter#GetExecutable',
\ 'command': function('ale_linters#go#gometalinter#GetCommand'), \ 'command_callback': 'ale_linters#go#gometalinter#GetCommand',
\ 'callback': 'ale_linters#go#gometalinter#Handler', \ 'callback': 'ale_linters#go#gometalinter#Handler',
\ 'lint_file': 1, \ 'lint_file': 1,
\}) \})

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