diff options
author | Pierre-Nicolas Clauss <pinicarus@protonmail.com> | 2021-01-23 19:06:59 +0100 |
---|---|---|
committer | Pierre-Nicolas Clauss <pinicarus@protonmail.com> | 2021-01-23 19:06:59 +0100 |
commit | 0ac7595fe97607ae99757787eba19cf0870be00d (patch) | |
tree | 43bebcf52c3caf7a22d26b9309d0beb58aa144a9 /ale_linters | |
parent | db96b007209f7ea0983c58cb1d18771f5a45a543 (diff) | |
parent | 9fd9435cd525b1d3c4470db0d514f72ed31cfece (diff) | |
download | ale-0ac7595fe97607ae99757787eba19cf0870be00d.zip |
Merge remote-tracking branch 'upstream/master'
Signed-off-by: Pierre-Nicolas Clauss <pinicarus@protonmail.com>
Diffstat (limited to 'ale_linters')
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', \}) |