summaryrefslogtreecommitdiff
path: root/ale_linters
diff options
context:
space:
mode:
authorPierre-Nicolas Clauss <pinicarus@protonmail.com>2021-01-23 19:06:59 +0100
committerPierre-Nicolas Clauss <pinicarus@protonmail.com>2021-01-23 19:06:59 +0100
commit0ac7595fe97607ae99757787eba19cf0870be00d (patch)
tree43bebcf52c3caf7a22d26b9309d0beb58aa144a9 /ale_linters
parentdb96b007209f7ea0983c58cb1d18771f5a45a543 (diff)
parent9fd9435cd525b1d3c4470db0d514f72ed31cfece (diff)
downloadale-0ac7595fe97607ae99757787eba19cf0870be00d.zip
Merge remote-tracking branch 'upstream/master'
Signed-off-by: Pierre-Nicolas Clauss <pinicarus@protonmail.com>
Diffstat (limited to 'ale_linters')
-rw-r--r--ale_linters/ada/adals.vim26
-rw-r--r--ale_linters/apkbuild/apkbuild_lint.vim12
-rw-r--r--ale_linters/apkbuild/secfixes_check.vim12
-rw-r--r--ale_linters/cpp/clangtidy.vim10
-rw-r--r--ale_linters/dafny/dafny.vim19
-rw-r--r--ale_linters/dart/analysis_server.vim29
-rw-r--r--ale_linters/elixir/credo.vim11
-rw-r--r--ale_linters/erlang/elvis.vim39
-rw-r--r--ale_linters/inko/inko.vim33
-rw-r--r--ale_linters/java/checkstyle.vim2
-rw-r--r--ale_linters/javascript/xo.vim23
-rw-r--r--ale_linters/json/spectral.vim14
-rw-r--r--ale_linters/julia/languageserver.vim4
-rw-r--r--ale_linters/nix/rnix_lsp.vim16
-rw-r--r--ale_linters/openapi/ibm_validator.vim58
-rw-r--r--ale_linters/openapi/yamllint.vim9
-rwxr-xr-xale_linters/php/intelephense.vim32
-rw-r--r--ale_linters/php/phpcs.vim2
-rw-r--r--ale_linters/php/tlint.vim80
-rw-r--r--ale_linters/python/jedils.vim34
-rw-r--r--ale_linters/r/languageserver.vim26
-rw-r--r--ale_linters/ruby/sorbet.vim5
-rw-r--r--ale_linters/rust/analyzer.vim2
-rw-r--r--ale_linters/salt/salt_lint.vim33
-rw-r--r--ale_linters/typescript/deno.vim25
-rw-r--r--ale_linters/typescript/tsserver.vim1
-rw-r--r--ale_linters/typescript/xo.vim23
-rw-r--r--ale_linters/vala/vala_lint.vim66
-rw-r--r--ale_linters/yaml/spectral.vim14
-rw-r--r--ale_linters/yaml/yamllint.vim43
30 files changed, 610 insertions, 93 deletions
diff --git a/ale_linters/ada/adals.vim b/ale_linters/ada/adals.vim
new file mode 100644
index 00000000..9a41e1df
--- /dev/null
+++ b/ale_linters/ada/adals.vim
@@ -0,0 +1,26 @@
+" Author: Bartek Jasicki http://github.com/thindil
+" Description: Support for Ada Language Server
+
+call ale#Set('ada_adals_executable', 'ada_language_server')
+call ale#Set('ada_adals_project', 'default.gpr')
+call ale#Set('ada_adals_encoding', 'utf-8')
+
+function! ale_linters#ada#adals#GetAdaLSConfig(buffer) abort
+ return {
+ \ 'ada.projectFile': ale#Var(a:buffer, 'ada_adals_project'),
+ \ 'ada.defaultCharset': ale#Var(a:buffer, 'ada_adals_encoding')
+ \}
+endfunction
+
+function! ale_linters#ada#adals#GetRootDirectory(buffer) abort
+ return fnamemodify(bufname(a:buffer), ':p:h')
+endfunction
+
+call ale#linter#Define('ada', {
+\ 'name': 'adals',
+\ 'lsp': 'stdio',
+\ 'executable': {b -> ale#Var(b, 'ada_adals_executable')},
+\ 'command': '%e',
+\ 'project_root': function('ale_linters#ada#adals#GetRootDirectory'),
+\ 'lsp_config': function('ale_linters#ada#adals#GetAdaLSConfig')
+\})
diff --git a/ale_linters/apkbuild/apkbuild_lint.vim b/ale_linters/apkbuild/apkbuild_lint.vim
new file mode 100644
index 00000000..285f5534
--- /dev/null
+++ b/ale_linters/apkbuild/apkbuild_lint.vim
@@ -0,0 +1,12 @@
+" Author: Leo <thinkabit.ukim@gmail.com>
+" Description: apkbuild-lint from atools linter for APKBUILDs
+
+call ale#Set('apkbuild_apkbuild_lint_executable', 'apkbuild-lint')
+
+call ale#linter#Define('apkbuild', {
+\ 'name': 'apkbuild_lint',
+\ 'output_stream': 'stdout',
+\ 'executable': {b -> ale#Var(b, 'apkbuild_apkbuild_lint_executable')},
+\ 'command': '%e %t',
+\ 'callback': 'ale#handlers#atools#Handle',
+\})
diff --git a/ale_linters/apkbuild/secfixes_check.vim b/ale_linters/apkbuild/secfixes_check.vim
new file mode 100644
index 00000000..c65267fd
--- /dev/null
+++ b/ale_linters/apkbuild/secfixes_check.vim
@@ -0,0 +1,12 @@
+" Author: Leo <thinkabit.ukim@gmail.com>
+" Description: secfixes-check from atools linter for APKBUILDs
+
+call ale#Set('apkbuild_secfixes_check_executable', 'secfixes-check')
+
+call ale#linter#Define('apkbuild', {
+\ 'name': 'secfixes_check',
+\ 'output_stream': 'stdout',
+\ 'executable': {b -> ale#Var(b, 'apkbuild_secfixes_check_executable')},
+\ 'command': '%e %t',
+\ 'callback': 'ale#handlers#atools#Handle',
+\})
diff --git a/ale_linters/cpp/clangtidy.vim b/ale_linters/cpp/clangtidy.vim
index 5e062d86..d6944aae 100644
--- a/ale_linters/cpp/clangtidy.vim
+++ b/ale_linters/cpp/clangtidy.vim
@@ -23,11 +23,13 @@ function! ale_linters#cpp#clangtidy#GetCommand(buffer, output) abort
let l:options = ale#Var(a:buffer, 'cpp_clangtidy_options')
let l:cflags = ale#c#GetCFlags(a:buffer, a:output)
let l:options .= !empty(l:options) ? ale#Pad(l:cflags) : l:cflags
- endif
- " Tell clang-tidy a .h header with a C++ filetype in Vim is a C++ file.
- if expand('#' . a:buffer) =~# '\.h$'
- let l:options .= !empty(l:options) ? ' -x c++' : '-x c++'
+ " Tell clang-tidy a .h header with a C++ filetype in Vim is a C++ file
+ " only when compile-commands.json file is not there. Adding these
+ " flags makes clang-tidy completely ignore compile commmands.
+ if expand('#' . a:buffer) =~# '\.h$'
+ let l:options .= !empty(l:options) ? ' -x c++' : '-x c++'
+ endif
endif
" Get the options to pass directly to clang-tidy
diff --git a/ale_linters/dafny/dafny.vim b/ale_linters/dafny/dafny.vim
index b5b90675..de7a7bb8 100644
--- a/ale_linters/dafny/dafny.vim
+++ b/ale_linters/dafny/dafny.vim
@@ -6,7 +6,7 @@ function! ale_linters#dafny#dafny#Handle(buffer, lines) abort
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
- \ 'bufnr': a:buffer,
+ \ 'filename': l:match[1],
\ 'col': l:match[3] + 0,
\ 'lnum': l:match[2] + 0,
\ 'text': l:match[5],
@@ -14,13 +14,28 @@ function! ale_linters#dafny#dafny#Handle(buffer, lines) abort
\ })
endfor
+ for l:match in ale#util#GetMatches(a:lines, '\v(.*)\((\d+),(\d+)\): (Verification of .{-} timed out after \d+ seconds)')
+ call add(l:output, {
+ \ 'bufnr': a:buffer,
+ \ 'col': l:match[3] + 0,
+ \ 'lnum': l:match[2] + 0,
+ \ 'text': l:match[4],
+ \ 'type': 'E',
+ \ })
+ endfor
+
return l:output
endfunction
+function! ale_linters#dafny#dafny#GetCommand(buffer) abort
+ return printf('dafny %%s /compile:0 /timeLimit:%d', ale#Var(a:buffer, 'dafny_dafny_timelimit'))
+endfunction
+
+call ale#Set('dafny_dafny_timelimit', 10)
call ale#linter#Define('dafny', {
\ 'name': 'dafny',
\ 'executable': 'dafny',
-\ 'command': 'dafny %s /compile:0',
+\ 'command': function('ale_linters#dafny#dafny#GetCommand'),
\ 'callback': 'ale_linters#dafny#dafny#Handle',
\ 'lint_file': 1,
\ })
diff --git a/ale_linters/dart/analysis_server.vim b/ale_linters/dart/analysis_server.vim
new file mode 100644
index 00000000..a6870da9
--- /dev/null
+++ b/ale_linters/dart/analysis_server.vim
@@ -0,0 +1,29 @@
+" Author: Nelson Yeung <nelsyeung@gmail.com>
+" Description: Check Dart files with dart analysis server LSP
+
+call ale#Set('dart_analysis_server_executable', 'dart')
+
+function! ale_linters#dart#analysis_server#GetProjectRoot(buffer) abort
+ " Note: pub only looks for pubspec.yaml, there's no point in adding
+ " support for pubspec.yml
+ let l:pubspec = ale#path#FindNearestFile(a:buffer, 'pubspec.yaml')
+
+ return !empty(l:pubspec) ? fnamemodify(l:pubspec, ':h:h') : '.'
+endfunction
+
+function! ale_linters#dart#analysis_server#GetCommand(buffer) abort
+ let l:executable = ale#Var(a:buffer, 'dart_analysis_server_executable')
+ let l:dart = resolve(exepath(l:executable))
+
+ return '%e '
+ \ . fnamemodify(l:dart, ':h') . '/snapshots/analysis_server.dart.snapshot'
+ \ . ' --lsp'
+endfunction
+
+call ale#linter#Define('dart', {
+\ 'name': 'analysis_server',
+\ 'lsp': 'stdio',
+\ 'executable': {b -> ale#Var(b, 'dart_analysis_server_executable')},
+\ 'command': function('ale_linters#dart#analysis_server#GetCommand'),
+\ 'project_root': function('ale_linters#dart#analysis_server#GetProjectRoot'),
+\})
diff --git a/ale_linters/elixir/credo.vim b/ale_linters/elixir/credo.vim
index 7c298502..892d47b9 100644
--- a/ale_linters/elixir/credo.vim
+++ b/ale_linters/elixir/credo.vim
@@ -45,6 +45,16 @@ function! ale_linters#elixir#credo#GetMode() abort
endif
endfunction
+function! ale_linters#elixir#credo#GetConfigFile() abort
+ let l:config_file = get(g:, 'ale_elixir_credo_config_file', '')
+
+ if empty(l:config_file)
+ return ''
+ endif
+
+ return ' --config-file ' . l:config_file
+endfunction
+
function! ale_linters#elixir#credo#GetCommand(buffer) abort
let l:project_root = ale#handlers#elixir#FindMixUmbrellaRoot(a:buffer)
let l:mode = ale_linters#elixir#credo#GetMode()
@@ -52,6 +62,7 @@ function! ale_linters#elixir#credo#GetCommand(buffer) abort
return ale#path#CdString(l:project_root)
\ . 'mix help credo && '
\ . 'mix credo ' . ale_linters#elixir#credo#GetMode()
+ \ . ale_linters#elixir#credo#GetConfigFile()
\ . ' --format=flycheck --read-from-stdin %s'
endfunction
diff --git a/ale_linters/erlang/elvis.vim b/ale_linters/erlang/elvis.vim
new file mode 100644
index 00000000..31dea3dd
--- /dev/null
+++ b/ale_linters/erlang/elvis.vim
@@ -0,0 +1,39 @@
+" Author: Dmitri Vereshchagin <dmitri.vereshchagin@gmail.com>
+" Description: Elvis linter for Erlang files
+
+call ale#Set('erlang_elvis_executable', 'elvis')
+
+function! ale_linters#erlang#elvis#Handle(buffer, lines) abort
+ let l:pattern = '\v:(\d+):[^:]+:(.+)'
+ let l:loclist = []
+
+ for l:match in ale#util#GetMatches(a:lines, l:pattern)
+ call add(l:loclist, {
+ \ 'lnum': str2nr(l:match[1]),
+ \ 'text': s:AbbreviateMessage(l:match[2]),
+ \ 'type': 'W',
+ \})
+ endfor
+
+ return l:loclist
+endfunction
+
+function! s:AbbreviateMessage(text) abort
+ let l:pattern = '\v\c^(line \d+ is too long):.*$'
+
+ return substitute(a:text, l:pattern, '\1.', '')
+endfunction
+
+function! s:GetCommand(buffer) abort
+ let l:file = ale#Escape(expand('#' . a:buffer . ':.'))
+
+ return '%e rock --output-format=parsable ' . l:file
+endfunction
+
+call ale#linter#Define('erlang', {
+\ 'name': 'elvis',
+\ 'callback': 'ale_linters#erlang#elvis#Handle',
+\ 'executable': {b -> ale#Var(b, 'erlang_elvis_executable')},
+\ 'command': function('s:GetCommand'),
+\ 'lint_file': 1,
+\})
diff --git a/ale_linters/inko/inko.vim b/ale_linters/inko/inko.vim
new file mode 100644
index 00000000..11558897
--- /dev/null
+++ b/ale_linters/inko/inko.vim
@@ -0,0 +1,33 @@
+" Author: Yorick Peterse <yorick@yorickpeterse.com>
+" Description: linting of Inko source code using the Inko compiler
+
+call ale#Set('inko_inko_executable', 'inko')
+
+function! ale_linters#inko#inko#GetCommand(buffer) abort
+ let l:include = ''
+
+ " Include the tests source directory, but only for test files.
+ if expand('#' . a:buffer . ':p') =~? '\vtests[/\\]test[/\\]'
+ let l:test_dir = ale#path#FindNearestDirectory(a:buffer, 'tests')
+
+ if isdirectory(l:test_dir)
+ let l:include = '--include ' . ale#Escape(l:test_dir)
+ endif
+ endif
+
+ " We use %s instead of %t so the compiler determines the correct module
+ " names for the file being edited. Not doing so may lead to errors in
+ " certain cases.
+ return '%e build --check --format=json'
+ \ . ale#Pad(l:include)
+ \ . ' %s'
+endfunction
+
+call ale#linter#Define('inko', {
+\ 'name': 'inko',
+\ 'executable': {b -> ale#Var(b, 'inko_inko_executable')},
+\ 'command': function('ale_linters#inko#inko#GetCommand'),
+\ 'callback': 'ale#handlers#inko#Handle',
+\ 'output_stream': 'stderr',
+\ 'lint_file': 1
+\})
diff --git a/ale_linters/java/checkstyle.vim b/ale_linters/java/checkstyle.vim
index ec7339d1..f00734e0 100644
--- a/ale_linters/java/checkstyle.vim
+++ b/ale_linters/java/checkstyle.vim
@@ -9,7 +9,7 @@ function! ale_linters#java#checkstyle#Handle(buffer, lines) abort
let l:output = []
" modern checkstyle versions
- let l:pattern = '\v\[(WARN|ERROR)\] [a-zA-Z]?:?[^:]+:(\d+):(\d+)?:? (.*) \[(.+)\]$'
+ let l:pattern = '\v\[(WARN|ERROR)\] [a-zA-Z]?:?[^:]+:(\d+):(\d+)?:? (.*) \[(.+)\]'
for l:match in ale#util#GetMatches(a:lines, l:pattern)
call add(l:output, {
diff --git a/ale_linters/javascript/xo.vim b/ale_linters/javascript/xo.vim
index e24f4a82..5e04ad5c 100644
--- a/ale_linters/javascript/xo.vim
+++ b/ale_linters/javascript/xo.vim
@@ -1,26 +1,9 @@
" Author: Daniel Lupu <lupu.daniel.f@gmail.com>
" Description: xo for JavaScript files
-call ale#Set('javascript_xo_executable', 'xo')
-call ale#Set('javascript_xo_use_global', get(g:, 'ale_use_global_executables', 0))
-call ale#Set('javascript_xo_options', '')
-
-function! ale_linters#javascript#xo#GetExecutable(buffer) abort
- return ale#node#FindExecutable(a:buffer, 'javascript_xo', [
- \ 'node_modules/.bin/xo',
- \])
-endfunction
-
-function! ale_linters#javascript#xo#GetCommand(buffer) abort
- return ale#Escape(ale_linters#javascript#xo#GetExecutable(a:buffer))
- \ . ' ' . ale#Var(a:buffer, 'javascript_xo_options')
- \ . ' --reporter json --stdin --stdin-filename %s'
-endfunction
-
-" xo uses eslint and the output format is the same
call ale#linter#Define('javascript', {
\ 'name': 'xo',
-\ 'executable': function('ale_linters#javascript#xo#GetExecutable'),
-\ 'command': function('ale_linters#javascript#xo#GetCommand'),
-\ 'callback': 'ale#handlers#eslint#HandleJSON',
+\ 'executable': function('ale#handlers#xo#GetExecutable'),
+\ 'command': function('ale#handlers#xo#GetLintCommand'),
+\ 'callback': 'ale#handlers#xo#HandleJSON',
\})
diff --git a/ale_linters/json/spectral.vim b/ale_linters/json/spectral.vim
new file mode 100644
index 00000000..c7d56234
--- /dev/null
+++ b/ale_linters/json/spectral.vim
@@ -0,0 +1,14 @@
+" Author: t2h5 <https://github.com/t2h5>
+" Description: Integration of Stoplight Spectral CLI with ALE.
+
+call ale#Set('json_spectral_executable', 'spectral')
+call ale#Set('json_spectral_use_global', get(g:, 'ale_use_global_executables', 0))
+
+call ale#linter#Define('json', {
+\ 'name': 'spectral',
+\ 'executable': {b -> ale#node#FindExecutable(b, 'json_spectral', [
+\ 'node_modules/.bin/spectral',
+\ ])},
+\ 'command': '%e lint --ignore-unknown-format -q -f text %t',
+\ 'callback': 'ale#handlers#spectral#HandleSpectralOutput'
+\})
diff --git a/ale_linters/julia/languageserver.vim b/ale_linters/julia/languageserver.vim
index 564bec39..999ad815 100644
--- a/ale_linters/julia/languageserver.vim
+++ b/ale_linters/julia/languageserver.vim
@@ -6,9 +6,9 @@ call ale#Set('julia_executable', 'julia')
function! ale_linters#julia#languageserver#GetCommand(buffer) abort
let l:julia_executable = ale#Var(a:buffer, 'julia_executable')
- let l:cmd_string = 'using LanguageServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, false); server.runlinter = true; run(server);'
+ let l:cmd_string = 'using LanguageServer; using Pkg; import StaticLint; import SymbolServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, dirname(Pkg.Types.Context().env.project_file)); server.runlinter = true; run(server);'
- return ale#Escape(l:julia_executable) . ' --startup-file=no --history-file=no -e ' . ale#Escape(l:cmd_string)
+ return ale#Escape(l:julia_executable) . ' --project=@. --startup-file=no --history-file=no -e ' . ale#Escape(l:cmd_string)
endfunction
call ale#linter#Define('julia', {
diff --git a/ale_linters/nix/rnix_lsp.vim b/ale_linters/nix/rnix_lsp.vim
new file mode 100644
index 00000000..949bed1c
--- /dev/null
+++ b/ale_linters/nix/rnix_lsp.vim
@@ -0,0 +1,16 @@
+" Author: jD91mZM2 <me@krake.one>
+" Description: rnix-lsp language client
+
+function! ale_linters#nix#rnix_lsp#GetProjectRoot(buffer) abort
+ " rnix-lsp does not yet use the project root, so getting it right is not
+ " important
+ return fnamemodify(a:buffer, ':h')
+endfunction
+
+call ale#linter#Define('nix', {
+\ 'name': 'rnix_lsp',
+\ 'lsp': 'stdio',
+\ 'executable': 'rnix-lsp',
+\ 'command': '%e',
+\ 'project_root': function('ale_linters#nix#rnix_lsp#GetProjectRoot'),
+\})
diff --git a/ale_linters/openapi/ibm_validator.vim b/ale_linters/openapi/ibm_validator.vim
new file mode 100644
index 00000000..446931a2
--- /dev/null
+++ b/ale_linters/openapi/ibm_validator.vim
@@ -0,0 +1,58 @@
+" Author: Horacio Sanson <hsanson@gmail.com>
+
+call ale#Set('openapi_ibm_validator_executable', 'lint-openapi')
+call ale#Set('openapi_ibm_validator_options', '')
+
+function! ale_linters#openapi#ibm_validator#GetCommand(buffer) abort
+ return '%e' . ale#Pad(ale#Var(a:buffer, 'openapi_ibm_validator_options'))
+ \ . ' %t'
+endfunction
+
+function! ale_linters#openapi#ibm_validator#Handle(buffer, lines) abort
+ let l:output = []
+ let l:type = 'E'
+ let l:message = ''
+ let l:nr = -1
+
+ for l:line in a:lines
+ let l:match = matchlist(l:line, '^errors$')
+
+ if !empty(l:match)
+ let l:type = 'E'
+ endif
+
+ let l:match = matchlist(l:line, '^warnings$')
+
+ if !empty(l:match)
+ let l:type = 'W'
+ endif
+
+ let l:match = matchlist(l:line, '^ *Message : *\(.\+\)$')
+
+ if !empty(l:match)
+ let l:message = l:match[1]
+ endif
+
+ let l:match = matchlist(l:line, '^ *Line *: *\(\d\+\)$')
+
+ if !empty(l:match)
+ let l:nr = l:match[1]
+
+ call add(l:output, {
+ \ 'lnum': l:nr + 0,
+ \ 'col': 0,
+ \ 'text': l:message,
+ \ 'type': l:type,
+ \})
+ endif
+ endfor
+
+ return l:output
+endfunction
+
+call ale#linter#Define('openapi', {
+\ 'name': 'ibm_validator',
+\ 'executable': {b -> ale#Var(b, 'openapi_ibm_validator_executable')},
+\ 'command': function('ale_linters#openapi#ibm_validator#GetCommand'),
+\ 'callback': 'ale_linters#openapi#ibm_validator#Handle',
+\})
diff --git a/ale_linters/openapi/yamllint.vim b/ale_linters/openapi/yamllint.vim
new file mode 100644
index 00000000..2b8952cc
--- /dev/null
+++ b/ale_linters/openapi/yamllint.vim
@@ -0,0 +1,9 @@
+call ale#Set('yaml_yamllint_executable', 'yamllint')
+call ale#Set('yaml_yamllint_options', '')
+
+call ale#linter#Define('openapi', {
+\ 'name': 'yamllint',
+\ 'executable': {b -> ale#Var(b, 'yaml_yamllint_executable')},
+\ 'command': function('ale#handlers#yamllint#GetCommand'),
+\ 'callback': 'ale#handlers#yamllint#Handle',
+\})
diff --git a/ale_linters/php/intelephense.vim b/ale_linters/php/intelephense.vim
new file mode 100755
index 00000000..aca619e3
--- /dev/null
+++ b/ale_linters/php/intelephense.vim
@@ -0,0 +1,32 @@
+" Author: Eric Stern <eric@ericstern.com>,
+" Arnold Chand <creativenull@outlook.com>
+" Description: Intelephense language server integration for ALE
+
+call ale#Set('php_intelephense_executable', 'intelephense')
+call ale#Set('php_intelephense_use_global', 1)
+call ale#Set('php_intelephense_config', {})
+
+function! ale_linters#php#intelephense#GetProjectRoot(buffer) abort
+ let l:composer_path = ale#path#FindNearestFile(a:buffer, 'composer.json')
+
+ if (!empty(l:composer_path))
+ return fnamemodify(l:composer_path, ':h')
+ endif
+
+ let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git')
+
+ return !empty(l:git_path) ? fnamemodify(l:git_path, ':h:h') : ''
+endfunction
+
+function! ale_linters#php#intelephense#GetInitializationOptions(buffer) abort
+ return ale#Var(a:buffer, 'php_intelephense_config')
+endfunction
+
+call ale#linter#Define('php', {
+\ 'name': 'intelephense',
+\ 'lsp': 'stdio',
+\ 'initialization_options': function('ale_linters#php#intelephense#GetInitializationOptions'),
+\ 'executable': {b -> ale#node#FindExecutable(b, 'php_intelephense', [])},
+\ 'command': '%e --stdio',
+\ 'project_root': function('ale_linters#php#intelephense#GetProjectRoot'),
+\})
diff --git a/ale_linters/php/phpcs.vim b/ale_linters/php/phpcs.vim
index 11b81e84..c5a3faa9 100644
--- a/ale_linters/php/phpcs.vim
+++ b/ale_linters/php/phpcs.vim
@@ -23,7 +23,7 @@ function! ale_linters#php#phpcs#Handle(buffer, lines) abort
" Matches against lines like the following:
"
" /path/to/some-filename.php:18:3: error - Line indented incorrectly; expected 4 spaces, found 2 (Generic.WhiteSpace.ScopeIndent.IncorrectExact)
- let l:pattern = '^.*:\(\d\+\):\(\d\+\): \(.\+\) - \(.\+\) (\(.\+\))$'
+ let l:pattern = '^.*:\(\d\+\):\(\d\+\): \(.\+\) - \(.\+\) (\(.\+\)).*$'
let l:output = []
for l:match in ale#util#GetMatches(a:lines, l:pattern)
diff --git a/ale_linters/php/tlint.vim b/ale_linters/php/tlint.vim
new file mode 100644
index 00000000..6bba8def
--- /dev/null
+++ b/ale_linters/php/tlint.vim
@@ -0,0 +1,80 @@
+" Author: Jose Soto <jose@tighten.co>
+"
+" Description: Tighten Opinionated PHP Linting
+" Website: https://github.com/tightenco/tlint
+
+call ale#Set('php_tlint_executable', 'tlint')
+call ale#Set('php_tlint_use_global', get(g:, 'ale_use_global_executables', 0))
+call ale#Set('php_tlint_options', '')
+
+function! ale_linters#php#tlint#GetProjectRoot(buffer) abort
+ let l:composer_path = ale#path#FindNearestFile(a:buffer, 'composer.json')
+
+ if !empty(l:composer_path)
+ return fnamemodify(l:composer_path, ':h')
+ endif
+
+ let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git')
+
+ return !empty(l:git_path) ? fnamemodify(l:git_path, ':h:h') : ''
+endfunction
+
+function! ale_linters#php#tlint#GetExecutable(buffer) abort
+ return ale#node#FindExecutable(a:buffer, 'php_tlint', [
+ \ 'vendor/bin/tlint',
+ \ 'tlint',
+ \])
+endfunction
+
+function! ale_linters#php#tlint#GetCommand(buffer) abort
+ let l:executable = ale_linters#php#tlint#GetExecutable(a:buffer)
+ let l:options = ale#Var(a:buffer, 'php_tlint_options')
+
+ return ale#node#Executable(a:buffer, l:executable)
+ \ . (!empty(l:options) ? ' ' . l:options : '')
+ \ . ' lint %s'
+endfunction
+
+function! ale_linters#php#tlint#Handle(buffer, lines) abort
+ " Matches against lines like the following:
+ "
+ " ! There should be 1 space around `.` concatenations, and additional lines should always start with a `.`
+ " 22 : ` $something = 'a'.'name';`
+ "
+ let l:loop_count = 0
+ let l:messages_pattern = '^\! \(.*\)'
+ let l:output = []
+ let l:pattern = '^\(\d\+\) \:'
+ let l:temp_messages = []
+
+ for l:message in ale#util#GetMatches(a:lines, l:messages_pattern)
+ call add(l:temp_messages, l:message)
+ endfor
+
+ let l:loop_count = 0
+
+ for l:match in ale#util#GetMatches(a:lines, l:pattern)
+ let l:num = l:match[1]
+ let l:text = l:temp_messages[l:loop_count]
+
+ call add(l:output, {
+ \ 'lnum': l:num,
+ \ 'col': 0,
+ \ 'text': l:text,
+ \ 'type': 'W',
+ \ 'sub_type': 'style',
+ \})
+
+ let l:loop_count += 1
+ endfor
+
+ return l:output
+endfunction
+
+call ale#linter#Define('php', {
+\ 'name': 'tlint',
+\ 'executable': function('ale_linters#php#tlint#GetExecutable'),
+\ 'command': function('ale_linters#php#tlint#GetCommand'),
+\ 'callback': 'ale_linters#php#tlint#Handle',
+\ 'project_root': function('ale_linters#php#tlint#GetProjectRoot'),
+\})
diff --git a/ale_linters/python/jedils.vim b/ale_linters/python/jedils.vim
new file mode 100644
index 00000000..eae5fb07
--- /dev/null
+++ b/ale_linters/python/jedils.vim
@@ -0,0 +1,34 @@
+" Author: Dalius Dobravolskas <dalius.dobravolskas@gmail.com>
+" Description: https://github.com/pappasam/jedi-language-server
+
+call ale#Set('python_jedils_executable', 'jedi-language-server')
+call ale#Set('python_jedils_use_global', get(g:, 'ale_use_global_executables', 0))
+call ale#Set('python_jedils_auto_pipenv', 0)
+
+function! ale_linters#python#jedils#GetExecutable(buffer) abort
+ if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_jedils_auto_pipenv'))
+ \ && ale#python#PipenvPresent(a:buffer)
+ return 'pipenv'
+ endif
+
+ return ale#python#FindExecutable(a:buffer, 'python_jedils', ['jedi-language-server'])
+endfunction
+
+function! ale_linters#python#jedils#GetCommand(buffer) abort
+ let l:executable = ale_linters#python#jedils#GetExecutable(a:buffer)
+
+ let l:exec_args = l:executable =~? 'pipenv$'
+ \ ? ' run jedi-language-server'
+ \ : ''
+
+ return ale#Escape(l:executable) . l:exec_args
+endfunction
+
+call ale#linter#Define('python', {
+\ 'name': 'jedils',
+\ 'lsp': 'stdio',
+\ 'executable': function('ale_linters#python#jedils#GetExecutable'),
+\ 'command': function('ale_linters#python#jedils#GetCommand'),
+\ 'project_root': function('ale#python#FindProjectRoot'),
+\ 'completion_filter': 'ale#completion#python#CompletionItemFilter',
+\})
diff --git a/ale_linters/r/languageserver.vim b/ale_linters/r/languageserver.vim
new file mode 100644
index 00000000..febe66bd
--- /dev/null
+++ b/ale_linters/r/languageserver.vim
@@ -0,0 +1,26 @@
+" Author: Eric Zhao <21zhaoe@protonmail.com>
+" Description: Implementation of the Language Server Protocol for R.
+
+call ale#Set('r_languageserver_cmd', 'languageserver::run()')
+call ale#Set('r_languageserver_config', {})
+
+function! ale_linters#r#languageserver#GetCommand(buffer) abort
+ let l:cmd_string = ale#Var(a:buffer, 'r_languageserver_cmd')
+
+ return 'Rscript --vanilla -e ' . ale#Escape(l:cmd_string)
+endfunction
+
+function! ale_linters#r#languageserver#GetProjectRoot(buffer) abort
+ let l:project_root = ale#path#FindNearestFile(a:buffer, '.Rprofile')
+
+ return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : fnamemodify(a:buffer, ':h')
+endfunction
+
+call ale#linter#Define('r', {
+\ 'name': 'languageserver',
+\ 'lsp': 'stdio',
+\ 'lsp_config': {b -> ale#Var(b, 'r_languageserver_config')},
+\ 'executable': 'Rscript',
+\ 'command': function('ale_linters#r#languageserver#GetCommand'),
+\ 'project_root': function('ale_linters#r#languageserver#GetProjectRoot')
+\})
diff --git a/ale_linters/ruby/sorbet.vim b/ale_linters/ruby/sorbet.vim
index cae0683c..c67e20cc 100644
--- a/ale_linters/ruby/sorbet.vim
+++ b/ale_linters/ruby/sorbet.vim
@@ -1,14 +1,17 @@
call ale#Set('ruby_sorbet_executable', 'srb')
call ale#Set('ruby_sorbet_options', '')
+call ale#Set('ruby_sorbet_enable_watchman', 0)
function! ale_linters#ruby#sorbet#GetCommand(buffer) abort
let l:executable = ale#Var(a:buffer, 'ruby_sorbet_executable')
let l:options = ale#Var(a:buffer, 'ruby_sorbet_options')
+ let l:enable_watchman = ale#Var(a:buffer, 'ruby_sorbet_enable_watchman')
return ale#ruby#EscapeExecutable(l:executable, 'srb')
\ . ' tc'
\ . (!empty(l:options) ? ' ' . l:options : '')
- \ . ' --lsp --disable-watchman'
+ \ . ' --lsp'
+ \ . (l:enable_watchman ? '' : ' --disable-watchman')
endfunction
call ale#linter#Define('ruby', {
diff --git a/ale_linters/rust/analyzer.vim b/ale_linters/rust/analyzer.vim
index 3666ec03..77d946f7 100644
--- a/ale_linters/rust/analyzer.vim
+++ b/ale_linters/rust/analyzer.vim
@@ -17,7 +17,7 @@ endfunction
call ale#linter#Define('rust', {
\ 'name': 'analyzer',
\ 'lsp': 'stdio',
-\ 'lsp_config': {b -> ale#Var(b, 'rust_analyzer_config')},
+\ 'initialization_options': {b -> ale#Var(b, 'rust_analyzer_config')},
\ 'executable': {b -> ale#Var(b, 'rust_analyzer_executable')},
\ 'command': function('ale_linters#rust#analyzer#GetCommand'),
\ 'project_root': function('ale_linters#rust#analyzer#GetProjectRoot'),
diff --git a/ale_linters/salt/salt_lint.vim b/ale_linters/salt/salt_lint.vim
new file mode 100644
index 00000000..47f66d83
--- /dev/null
+++ b/ale_linters/salt/salt_lint.vim
@@ -0,0 +1,33 @@
+" Author: Benjamin BINIER <poulpatine@gmail.com>
+" Description: salt-lint, saltstack linter
+
+call ale#Set('salt_salt_lint_executable', 'salt-lint')
+call ale#Set('salt_salt_lint_options', '')
+
+function! ale_linters#salt#salt_lint#GetCommand(buffer) abort
+ return '%e' . ale#Pad(ale#Var(a:buffer, 'salt_salt_lint_options'))
+ \ . ' --json'
+endfunction
+
+function! ale_linters#salt#salt_lint#Handle(buffer, lines) abort
+ let l:output = []
+
+ for l:error in ale#util#FuzzyJSONDecode(a:lines, [])
+ call add(l:output, {
+ \ 'lnum': l:error.linenumber + 0,
+ \ 'code': l:error.id + 0,
+ \ 'text': l:error.message,
+ \ 'type': l:error.severity is# 'HIGH' ? 'E' : 'W',
+ \})
+ endfor
+
+ return l:output
+endfunction
+
+call ale#linter#Define('salt', {
+\ 'name': 'salt_lint',
+\ 'aliases': ['salt-lint'],
+\ 'executable': {b -> ale#Var(b, 'salt_salt_lint_executable')},
+\ 'command': function('ale_linters#salt#salt_lint#GetCommand'),
+\ 'callback': 'ale_linters#salt#salt_lint#Handle'
+\})
diff --git a/ale_linters/typescript/deno.vim b/ale_linters/typescript/deno.vim
new file mode 100644
index 00000000..051cb208
--- /dev/null
+++ b/ale_linters/typescript/deno.vim
@@ -0,0 +1,25 @@
+" Author: Mohammed Chelouti - https://github.com/motato1
+" Description: Deno lsp linter for TypeScript files.
+
+call ale#linter#Define('typescript', {
+\ 'name': 'deno',
+\ 'lsp': 'stdio',
+\ 'executable': function('ale#handlers#deno#GetExecutable'),
+\ 'command': '%e lsp',
+\ 'project_root': function('ale#handlers#deno#GetProjectRoot'),
+\ 'initialization_options': function('ale_linters#typescript#deno#GetInitializationOptions'),
+\})
+
+function! ale_linters#typescript#deno#GetInitializationOptions(buffer) abort
+ let l:options = {
+ \ 'enable': v:true,
+ \ 'lint': v:true,
+ \ 'unstable': v:false,
+ \ }
+
+ if ale#Var(a:buffer, 'deno_unstable')
+ let l:options.unstable = v:true
+ endif
+
+ return l:options
+endfunction
diff --git a/ale_linters/typescript/tsserver.vim b/ale_linters/typescript/tsserver.vim
index 840889f3..4726e40d 100644
--- a/ale_linters/typescript/tsserver.vim
+++ b/ale_linters/typescript/tsserver.vim
@@ -9,6 +9,7 @@ call ale#linter#Define('typescript', {
\ 'name': 'tsserver',
\ 'lsp': 'tsserver',
\ 'executable': {b -> ale#node#FindExecutable(b, 'typescript_tsserver', [
+\ '.yarn/sdks/typescript/bin/tsserver',
\ 'node_modules/.bin/tsserver',
\ ])},
\ 'command': '%e',
diff --git a/ale_linters/typescript/xo.vim b/ale_linters/typescript/xo.vim
index 0a3a717b..6f4ee50c 100644
--- a/ale_linters/typescript/xo.vim
+++ b/ale_linters/typescript/xo.vim
@@ -1,23 +1,6 @@
-call ale#Set('typescript_xo_executable', 'xo')
-call ale#Set('typescript_xo_use_global', get(g:, 'ale_use_global_executables', 0))
-call ale#Set('typescript_xo_options', '')
-
-function! ale_linters#typescript#xo#GetExecutable(buffer) abort
- return ale#node#FindExecutable(a:buffer, 'typescript_xo', [
- \ 'node_modules/.bin/xo',
- \])
-endfunction
-
-function! ale_linters#typescript#xo#GetCommand(buffer) abort
- return ale#Escape(ale_linters#typescript#xo#GetExecutable(a:buffer))
- \ . ale#Pad(ale#Var(a:buffer, 'typescript_xo_options'))
- \ . ' --reporter json --stdin --stdin-filename %s'
-endfunction
-
-" xo uses eslint and the output format is the same
call ale#linter#Define('typescript', {
\ 'name': 'xo',
-\ 'executable': function('ale_linters#typescript#xo#GetExecutable'),
-\ 'command': function('ale_linters#typescript#xo#GetCommand'),
-\ 'callback': 'ale#handlers#eslint#HandleJSON',
+\ 'executable': function('ale#handlers#xo#GetExecutable'),
+\ 'command': function('ale#handlers#xo#GetLintCommand'),
+\ 'callback': 'ale#handlers#xo#HandleJSON',
\})
diff --git a/ale_linters/vala/vala_lint.vim b/ale_linters/vala/vala_lint.vim
new file mode 100644
index 00000000..7f8a566a
--- /dev/null
+++ b/ale_linters/vala/vala_lint.vim
@@ -0,0 +1,66 @@
+" Author: Atsuya Takagi <asoftonight@gmail.com>
+" Description: A linter for Vala using Vala-Lint.
+
+call ale#Set('vala_vala_lint_config_filename', 'vala-lint.conf')
+call ale#Set('vala_vala_lint_executable', 'io.elementary.vala-lint')
+
+function! ale_linters#vala#vala_lint#GetExecutable(buffer) abort
+ return ale#Var(a:buffer, 'vala_vala_lint_executable')
+endfunction
+
+function! ale_linters#vala#vala_lint#GetCommand(buffer) abort
+ let l:command = ale_linters#vala#vala_lint#GetExecutable(a:buffer)
+
+ let l:config_filename = ale#Var(a:buffer, 'vala_vala_lint_config_filename')
+ let l:config_path = ale#path#FindNearestFile(a:buffer, l:config_filename)
+
+ if !empty(l:config_path)
+ let l:command .= ' -c ' . l:config_path
+ endif
+
+ return l:command . ' %s'
+endfunction
+
+function! ale_linters#vala#vala_lint#Handle(buffer, lines) abort
+ let l:pattern = '^\s*\(\d\+\)\.\(\d\+\)\s\+\(error\|warn\)\s\+\(.\+\)\s\([A-Za-z0-9_\-]\+\)'
+ let l:output = []
+
+ for l:line in a:lines
+ " remove color escape sequences since vala-lint doesn't support
+ " output without colors
+ let l:cleaned_line = substitute(l:line, '\e\[[0-9;]\+[mK]', '', 'g')
+ let l:match = matchlist(l:cleaned_line, l:pattern)
+
+ if len(l:match) == 0
+ continue
+ endif
+
+ let l:refined_type = l:match[3] is# 'warn' ? 'W' : 'E'
+ let l:cleaned_text = substitute(l:match[4], '^\s*\(.\{-}\)\s*$', '\1', '')
+
+ let l:lnum = l:match[1] + 0
+ let l:column = l:match[2] + 0
+ let l:type = l:refined_type
+ let l:text = l:cleaned_text
+ let l:code = l:match[5]
+
+ call add(l:output, {
+ \ 'lnum': l:lnum,
+ \ 'col': l:column,
+ \ 'text': l:text,
+ \ 'type': l:type,
+ \ 'code': l:code,
+ \})
+ endfor
+
+ return l:output
+endfunction
+
+call ale#linter#Define('vala', {
+\ 'name': 'vala_lint',
+\ 'output_stream': 'stdout',
+\ 'executable': function('ale_linters#vala#vala_lint#GetExecutable'),
+\ 'command': function('ale_linters#vala#vala_lint#GetCommand'),
+\ 'callback': 'ale_linters#vala#vala_lint#Handle',
+\ 'lint_file': 1,
+\})
diff --git a/ale_linters/yaml/spectral.vim b/ale_linters/yaml/spectral.vim
new file mode 100644
index 00000000..bd4623a5
--- /dev/null
+++ b/ale_linters/yaml/spectral.vim
@@ -0,0 +1,14 @@
+" Author: t2h5 <https://github.com/t2h5>
+" Description: Integration of Stoplight Spectral CLI with ALE.
+
+call ale#Set('yaml_spectral_executable', 'spectral')
+call ale#Set('yaml_spectral_use_global', get(g:, 'ale_use_global_executables', 0))
+
+call ale#linter#Define('yaml', {
+\ 'name': 'spectral',
+\ 'executable': {b -> ale#node#FindExecutable(b, 'yaml_spectral', [
+\ 'node_modules/.bin/spectral',
+\ ])},
+\ 'command': '%e lint --ignore-unknown-format -q -f text %t',
+\ 'callback': 'ale#handlers#spectral#HandleSpectralOutput'
+\})
diff --git a/ale_linters/yaml/yamllint.vim b/ale_linters/yaml/yamllint.vim
index bedb7bf1..39011df1 100644
--- a/ale_linters/yaml/yamllint.vim
+++ b/ale_linters/yaml/yamllint.vim
@@ -3,48 +3,9 @@
call ale#Set('yaml_yamllint_executable', 'yamllint')
call ale#Set('yaml_yamllint_options', '')
-function! ale_linters#yaml#yamllint#GetCommand(buffer) abort
- return '%e' . ale#Pad(ale#Var(a:buffer, 'yaml_yamllint_options'))
- \ . ' -f parsable %t'
-endfunction
-
-function! ale_linters#yaml#yamllint#Handle(buffer, lines) abort
- " Matches patterns line the following:
- " something.yaml:1:1: [warning] missing document start "---" (document-start)
- " something.yml:2:1: [error] syntax error: expected the node content, but found '<stream end>'
- let l:pattern = '\v^.*:(\d+):(\d+): \[(error|warning)\] (.+)$'
- let l:output = []
-
- for l:match in ale#util#GetMatches(a:lines, l:pattern)
- let l:item = {
- \ 'lnum': l:match[1] + 0,
- \ 'col': l:match[2] + 0,
- \ 'text': l:match[4],
- \ 'type': l:match[3] is# 'error' ? 'E' : 'W',
- \}
-
- let l:code_match = matchlist(l:item.text, '\v^(.+) \(([^)]+)\)$')
-
- if !empty(l:code_match)
- if l:code_match[2] is# 'trailing-spaces'
- \&& !ale#Var(a:buffer, 'warn_about_trailing_whitespace')
- " Skip warnings for trailing whitespace if the option is off.
- continue
- endif
-
- let l:item.text = l:code_match[1]
- let l:item.code = l:code_match[2]
- endif
-
- call add(l:output, l:item)
- endfor
-
- return l:output
-endfunction
-
call ale#linter#Define('yaml', {
\ 'name': 'yamllint',
\ 'executable': {b -> ale#Var(b, 'yaml_yamllint_executable')},
-\ 'command': function('ale_linters#yaml#yamllint#GetCommand'),
-\ 'callback': 'ale_linters#yaml#yamllint#Handle',
+\ 'command': function('ale#handlers#yamllint#GetCommand'),
+\ 'callback': 'ale#handlers#yamllint#Handle',
\})