diff options
Diffstat (limited to 'ale_linters')
160 files changed, 1841 insertions, 1092 deletions
diff --git a/ale_linters/ada/gcc.vim b/ale_linters/ada/gcc.vim new file mode 100644 index 00000000..d6f973ae --- /dev/null +++ b/ale_linters/ada/gcc.vim @@ -0,0 +1,54 @@ +" 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#engine#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_callback': ale#VarFunc('ada_gcc_executable'), +\ 'command_callback': 'ale_linters#ada#gcc#GetCommand', +\ 'callback': 'ale_linters#ada#gcc#Handle', +\}) diff --git a/ale_linters/ansible/ansible_lint.vim b/ale_linters/ansible/ansible_lint.vim index 0b3b39c8..99fff6c3 100644 --- a/ale_linters/ansible/ansible_lint.vim +++ b/ale_linters/ansible/ansible_lint.vim @@ -1,6 +1,12 @@ " Author: Bjorn Neergaard <bjorn@neersighted.com> " 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 for l:line in a:lines[:10] if match(l:line, '^Traceback') >= 0 @@ -42,8 +48,9 @@ function! ale_linters#ansible#ansible_lint#Handle(buffer, lines) abort endfunction call ale#linter#Define('ansible', { -\ 'name': 'ansible', -\ 'executable': 'ansible', -\ 'command': 'ansible-lint -p %t', +\ 'name': 'ansible_lint', +\ 'aliases': ['ansible', 'ansible-lint'], +\ 'executable_callback': 'ale_linters#ansible#ansible_lint#GetExecutable', +\ 'command': '%e -p %t', \ 'callback': 'ale_linters#ansible#ansible_lint#Handle', \}) diff --git a/ale_linters/apiblueprint/drafter.vim b/ale_linters/apiblueprint/drafter.vim index 198709f9..5d40c53a 100644 --- a/ale_linters/apiblueprint/drafter.vim +++ b/ale_linters/apiblueprint/drafter.vim @@ -16,10 +16,12 @@ function! ale_linters#apiblueprint#drafter#HandleErrors(buffer, lines) abort \ 'lnum': l:match[3] + 0, \ 'col': l:match[4] + 0, \} + if l:match[5] isnot# '' let l:item.end_lnum = l:match[6] + 0 let l:item.end_col = l:match[7] + 0 endif + call add(l:output, l:item) endfor diff --git a/ale_linters/asciidoc/vale.vim b/ale_linters/asciidoc/vale.vim new file mode 100644 index 00000000..b3cf4547 --- /dev/null +++ b/ale_linters/asciidoc/vale.vim @@ -0,0 +1,9 @@ +" 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', +\}) diff --git a/ale_linters/asm/gcc.vim b/ale_linters/asm/gcc.vim index 4ac876f8..fdd0ee83 100644 --- a/ale_linters/asm/gcc.vim +++ b/ale_linters/asm/gcc.vim @@ -4,15 +4,10 @@ call ale#Set('asm_gcc_executable', 'gcc') 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 - return ale#Escape(ale_linters#asm#gcc#GetExecutable(a:buffer)) - \ . ' -x assembler -fsyntax-only ' - \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) - \ . ' ' . ale#Var(a:buffer, 'asm_gcc_options') . ' -' + return '%e -x assembler -fsyntax-only ' + \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) + \ . ' ' . ale#Var(a:buffer, 'asm_gcc_options') . ' -' endfunction function! ale_linters#asm#gcc#Handle(buffer, lines) abort @@ -33,7 +28,7 @@ endfunction call ale#linter#Define('asm', { \ 'name': 'gcc', \ 'output_stream': 'stderr', -\ 'executable_callback': 'ale_linters#asm#gcc#GetExecutable', +\ 'executable_callback': ale#VarFunc('asm_gcc_executable'), \ 'command_callback': 'ale_linters#asm#gcc#GetCommand', \ 'callback': 'ale_linters#asm#gcc#Handle', \}) diff --git a/ale_linters/awk/gawk.vim b/ale_linters/awk/gawk.vim index 8b60815f..eb92e45e 100644 --- a/ale_linters/awk/gawk.vim +++ b/ale_linters/awk/gawk.vim @@ -1,29 +1,21 @@ " Author: kmarc <korondi.mark@gmail.com> " Description: This file adds support for using GNU awk with sripts. -let g:ale_awk_gawk_executable = -\ get(g:, 'ale_awk_gawk_executable', 'gawk') - -let g:ale_awk_gawk_options = -\ get(g:, 'ale_awk_gawk_options', '') - -function! ale_linters#awk#gawk#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'awk_gawk_executable') -endfunction +call ale#Set('awk_gawk_executable', 'gawk') +call ale#Set('awk_gawk_options', '') function! ale_linters#awk#gawk#GetCommand(buffer) abort " note the --source 'BEGIN ...' is to prevent " gawk from attempting to execute the body of the script " it is linting. - return ale#Escape(ale_linters#awk#gawk#GetExecutable(a:buffer)) - \ . " --source 'BEGIN { exit } END { exit 1 }'" + return '%e --source ' . ale#Escape('BEGIN { exit } END { exit 1 }') \ . ale#Pad(ale#Var(a:buffer, 'awk_gawk_options')) - \ . ' ' . '-f %t --lint /dev/null' + \ . ' -f %t --lint /dev/null' endfunction call ale#linter#Define('awk', { \ 'name': 'gawk', -\ 'executable_callback': 'ale_linters#awk#gawk#GetExecutable', +\ 'executable_callback': ale#VarFunc('awk_gawk_executable'), \ 'command_callback': 'ale_linters#awk#gawk#GetCommand', \ 'callback': 'ale#handlers#gawk#HandleGawkFormat', \ 'output_stream': 'both' diff --git a/ale_linters/c/ccls.vim b/ale_linters/c/ccls.vim new file mode 100644 index 00000000..5dc2339f --- /dev/null +++ b/ale_linters/c/ccls.vim @@ -0,0 +1,14 @@ +" 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_callback': ale#VarFunc('c_ccls_executable'), +\ 'command': '%e', +\ 'project_root_callback': 'ale#handlers#ccls#GetProjectRoot', +\ 'initialization_options_callback':ale#VarFunc('c_ccls_init_options'), +\}) diff --git a/ale_linters/c/clang.vim b/ale_linters/c/clang.vim index ddec4fcb..f1bd675b 100644 --- a/ale_linters/c/clang.vim +++ b/ale_linters/c/clang.vim @@ -4,29 +4,24 @@ call ale#Set('c_clang_executable', 'clang') call ale#Set('c_clang_options', '-std=c11 -Wall') -function! ale_linters#c#clang#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'c_clang_executable') -endfunction - function! ale_linters#c#clang#GetCommand(buffer, output) abort let l:cflags = ale#c#GetCFlags(a:buffer, a:output) " -iquote with the directory the file is in makes #include work for " headers in the same directory. - return ale#Escape(ale_linters#c#clang#GetExecutable(a:buffer)) - \ . ' -S -x c -fsyntax-only ' - \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' - \ . l:cflags - \ . ale#Var(a:buffer, 'c_clang_options') . ' -' + return '%e -S -x c -fsyntax-only' + \ . ' -iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) + \ . ale#Pad(l:cflags) + \ . ale#Pad(ale#Var(a:buffer, 'c_clang_options')) . ' -' endfunction call ale#linter#Define('c', { \ 'name': 'clang', \ 'output_stream': 'stderr', -\ 'executable_callback': 'ale_linters#c#clang#GetExecutable', +\ 'executable_callback': ale#VarFunc('c_clang_executable'), \ 'command_chain': [ \ {'callback': 'ale#c#GetMakeCommand', 'output_stream': 'stdout'}, \ {'callback': 'ale_linters#c#clang#GetCommand'} \ ], -\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', +\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes', \}) diff --git a/ale_linters/c/clangd.vim b/ale_linters/c/clangd.vim index 5aa2e221..6cad601a 100644 --- a/ale_linters/c/clangd.vim +++ b/ale_linters/c/clangd.vim @@ -6,24 +6,18 @@ call ale#Set('c_clangd_options', '') function! ale_linters#c#clangd#GetProjectRoot(buffer) abort let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json') - return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' -endfunction -function! ale_linters#c#clangd#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'c_clangd_executable') + return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' endfunction function! ale_linters#c#clangd#GetCommand(buffer) abort - let l:executable = ale_linters#c#clangd#GetExecutable(a:buffer) - let l:options = ale#Var(a:buffer, 'c_clangd_options') - - return ale#Escape(l:executable) . (!empty(l:options) ? ' ' . l:options : '') + return '%e' . ale#Pad(ale#Var(a:buffer, 'c_clangd_options')) endfunction call ale#linter#Define('c', { \ 'name': 'clangd', \ 'lsp': 'stdio', -\ 'executable_callback': 'ale_linters#c#clangd#GetExecutable', +\ 'executable_callback': ale#VarFunc('c_clangd_executable'), \ 'command_callback': 'ale_linters#c#clangd#GetCommand', \ 'project_root_callback': 'ale_linters#c#clangd#GetProjectRoot', \}) diff --git a/ale_linters/c/clangtidy.vim b/ale_linters/c/clangtidy.vim index 47faa1ef..4f334655 100644 --- a/ale_linters/c/clangtidy.vim +++ b/ale_linters/c/clangtidy.vim @@ -10,44 +10,22 @@ call ale#Set('c_clangtidy_executable', 'clang-tidy') " Consult the check list in clang-tidy's documentation: " 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. " This will disable compile_commands.json detection. call ale#Set('c_clangtidy_options', '') call ale#Set('c_build_dir', '') -function! ale_linters#c#clangtidy#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'c_clangtidy_executable') -endfunction - -function! s:GetBuildDirectory(buffer) abort - " Don't include build directory for header files, as compile_commands.json - " files don't consider headers to be translation units, and provide no - " commands for compiling header files. - if expand('#' . a:buffer) =~# '\v\.(h|hpp)$' - return '' - endif - - let l:build_dir = ale#Var(a:buffer, 'c_build_dir') - - " c_build_dir has the priority if defined - if !empty(l:build_dir) - return l:build_dir - endif - - return ale#c#FindCompileCommands(a:buffer) -endfunction - function! ale_linters#c#clangtidy#GetCommand(buffer) abort let l:checks = join(ale#Var(a:buffer, 'c_clangtidy_checks'), ',') - let l:build_dir = s:GetBuildDirectory(a:buffer) + let l:build_dir = ale#c#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)) + return '%e' \ . (!empty(l:checks) ? ' -checks=' . ale#Escape(l:checks) : '') \ . ' %s' \ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '') @@ -57,7 +35,7 @@ endfunction call ale#linter#Define('c', { \ 'name': 'clangtidy', \ 'output_stream': 'stdout', -\ 'executable_callback': 'ale_linters#c#clangtidy#GetExecutable', +\ 'executable_callback': ale#VarFunc('c_clangtidy_executable'), \ 'command_callback': 'ale_linters#c#clangtidy#GetCommand', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'lint_file': 1, diff --git a/ale_linters/c/cppcheck.vim b/ale_linters/c/cppcheck.vim index 4db93f74..5e8c7936 100644 --- a/ale_linters/c/cppcheck.vim +++ b/ale_linters/c/cppcheck.vim @@ -4,10 +4,6 @@ call ale#Set('c_cppcheck_executable', 'cppcheck') 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 " Search upwards from the file for compile_commands.json. " @@ -23,8 +19,7 @@ function! ale_linters#c#cppcheck#GetCommand(buffer) abort \ : '' return l:cd_command - \ . ale#Escape(ale_linters#c#cppcheck#GetExecutable(a:buffer)) - \ . ' -q --language=c ' + \ . '%e -q --language=c ' \ . l:compile_commands_option \ . ale#Var(a:buffer, 'c_cppcheck_options') \ . ' %t' @@ -33,7 +28,7 @@ endfunction call ale#linter#Define('c', { \ 'name': 'cppcheck', \ 'output_stream': 'both', -\ 'executable_callback': 'ale_linters#c#cppcheck#GetExecutable', +\ 'executable_callback': ale#VarFunc('c_cppcheck_executable'), \ 'command_callback': 'ale_linters#c#cppcheck#GetCommand', \ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat', \}) diff --git a/ale_linters/c/cquery.vim b/ale_linters/c/cquery.vim new file mode 100644 index 00000000..a20782a2 --- /dev/null +++ b/ale_linters/c/cquery.vim @@ -0,0 +1,28 @@ +" 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 + let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json') + + if empty(l:project_root) + let l:project_root = ale#path#FindNearestFile(a:buffer, '.cquery') + endif + + return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' +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_callback': ale#VarFunc('c_cquery_executable'), +\ 'command': '%e', +\ 'project_root_callback': 'ale_linters#c#cquery#GetProjectRoot', +\ 'initialization_options_callback': 'ale_linters#c#cquery#GetInitializationOptions', +\}) diff --git a/ale_linters/c/flawfinder.vim b/ale_linters/c/flawfinder.vim index df6fbebe..7e1f6769 100644 --- a/ale_linters/c/flawfinder.vim +++ b/ale_linters/c/flawfinder.vim @@ -6,18 +6,12 @@ call ale#Set('c_flawfinder_options', '') call ale#Set('c_flawfinder_minlevel', 1) call ale#Set('c_flawfinder_error_severity', 6) -function! ale_linters#c#flawfinder#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'c_flawfinder_executable') -endfunction - function! ale_linters#c#flawfinder#GetCommand(buffer) abort - " Set the minimum vulnerability level for flawfinder to bother with 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') + return '%e -CDQS' + \ . ale#Pad(ale#Var(a:buffer, 'c_flawfinder_options')) \ . l:minlevel \ . ' %t' endfunction @@ -25,7 +19,7 @@ endfunction call ale#linter#Define('c', { \ 'name': 'flawfinder', \ 'output_stream': 'stdout', -\ 'executable_callback': 'ale_linters#c#flawfinder#GetExecutable', +\ 'executable_callback': ale#VarFunc('c_flawfinder_executable'), \ 'command_callback': 'ale_linters#c#flawfinder#GetCommand', \ 'callback': 'ale#handlers#flawfinder#HandleFlawfinderFormat', \}) diff --git a/ale_linters/c/gcc.vim b/ale_linters/c/gcc.vim index 98563952..60ecb712 100644 --- a/ale_linters/c/gcc.vim +++ b/ale_linters/c/gcc.vim @@ -4,29 +4,24 @@ call ale#Set('c_gcc_executable', 'gcc') call ale#Set('c_gcc_options', '-std=c11 -Wall') -function! ale_linters#c#gcc#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'c_gcc_executable') -endfunction - function! ale_linters#c#gcc#GetCommand(buffer, output) abort let l:cflags = ale#c#GetCFlags(a:buffer, a:output) " -iquote with the directory the file is in makes #include work for " headers in the same directory. - return ale#Escape(ale_linters#c#gcc#GetExecutable(a:buffer)) - \ . ' -S -x c -fsyntax-only ' - \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' - \ . l:cflags - \ . ale#Var(a:buffer, 'c_gcc_options') . ' -' + return '%e -S -x c -fsyntax-only' + \ . ' -iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) + \ . ale#Pad(l:cflags) + \ . ale#Pad(ale#Var(a:buffer, 'c_gcc_options')) . ' -' endfunction call ale#linter#Define('c', { \ 'name': 'gcc', \ 'output_stream': 'stderr', -\ 'executable_callback': 'ale_linters#c#gcc#GetExecutable', +\ 'executable_callback': ale#VarFunc('c_gcc_executable'), \ 'command_chain': [ \ {'callback': 'ale#c#GetMakeCommand', 'output_stream': 'stdout'}, \ {'callback': 'ale_linters#c#gcc#GetCommand'} \ ], -\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', +\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes', \}) diff --git a/ale_linters/chef/foodcritic.vim b/ale_linters/chef/foodcritic.vim index 2c28246c..c86336d6 100644 --- a/ale_linters/chef/foodcritic.vim +++ b/ale_linters/chef/foodcritic.vim @@ -6,17 +6,10 @@ call ale#Set('chef_foodcritic_executable', 'foodcritic') 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 - let l:executable = ale_linters#chef#foodcritic#GetExecutable(a:buffer) let l:options = ale#Var(a:buffer, 'chef_foodcritic_options') - return ale#Escape(l:executable) - \ . (!empty(l:options) ? ' ' . escape(l:options, '~') : '') - \ . ' %s' + return '%e' . ale#Pad(escape(l:options, '~')) . ' %s' endfunction function! ale_linters#chef#foodcritic#Handle(buffer, lines) abort @@ -41,7 +34,7 @@ endfunction call ale#linter#Define('chef', { \ 'name': 'foodcritic', -\ 'executable_callback': 'ale_linters#chef#foodcritic#GetExecutable', +\ 'executable_callback': ale#VarFunc('chef_foodcritic_executable'), \ 'command_callback': 'ale_linters#chef#foodcritic#GetCommand', \ 'callback': 'ale_linters#chef#foodcritic#Handle', \ 'lint_file': 1, diff --git a/ale_linters/clojure/joker.vim b/ale_linters/clojure/joker.vim index e78066fe..2f61148b 100644 --- a/ale_linters/clojure/joker.vim +++ b/ale_linters/clojure/joker.vim @@ -9,9 +9,11 @@ function! ale_linters#clojure#joker#HandleJokerFormat(buffer, lines) abort for l:match in ale#util#GetMatches(a:lines, l:pattern) let l:type = 'E' + if l:match[4] is? 'Parse warning' let l:type = 'W' endif + call add(l:output, { \ 'lnum': l:match[1] + 0, \ 'col': l:match[2] + 0, @@ -27,6 +29,6 @@ call ale#linter#Define('clojure', { \ 'name': 'joker', \ 'output_stream': 'stderr', \ 'executable': 'joker', -\ 'command': 'joker --lint %t', +\ 'command': 'joker --working-dir %s --lint %t', \ 'callback': 'ale_linters#clojure#joker#HandleJokerFormat', \}) diff --git a/ale_linters/cpp/ccls.vim b/ale_linters/cpp/ccls.vim new file mode 100644 index 00000000..501fd685 --- /dev/null +++ b/ale_linters/cpp/ccls.vim @@ -0,0 +1,14 @@ +" 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_callback': ale#VarFunc('cpp_ccls_executable'), +\ 'command': '%e', +\ 'project_root_callback': 'ale#handlers#ccls#GetProjectRoot', +\ 'initialization_options_callback': ale#VarFunc('cpp_ccls_init_options'), +\}) diff --git a/ale_linters/cpp/clang.vim b/ale_linters/cpp/clang.vim index e8d96187..649c5993 100644 --- a/ale_linters/cpp/clang.vim +++ b/ale_linters/cpp/clang.vim @@ -4,29 +4,24 @@ call ale#Set('cpp_clang_executable', 'clang++') call ale#Set('cpp_clang_options', '-std=c++14 -Wall') -function! ale_linters#cpp#clang#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'cpp_clang_executable') -endfunction - function! ale_linters#cpp#clang#GetCommand(buffer, output) abort let l:cflags = ale#c#GetCFlags(a:buffer, a:output) " -iquote with the directory the file is in makes #include work for " headers in the same directory. - return ale#Escape(ale_linters#cpp#clang#GetExecutable(a:buffer)) - \ . ' -S -x c++ -fsyntax-only ' - \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' - \ . l:cflags - \ . ale#Var(a:buffer, 'cpp_clang_options') . ' -' + return '%e -S -x c++ -fsyntax-only' + \ . ' -iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) + \ . ale#Pad(l:cflags) + \ . ale#Pad(ale#Var(a:buffer, 'cpp_clang_options')) . ' -' endfunction call ale#linter#Define('cpp', { \ 'name': 'clang', \ 'output_stream': 'stderr', -\ 'executable_callback': 'ale_linters#cpp#clang#GetExecutable', +\ 'executable_callback': ale#VarFunc('cpp_clang_executable'), \ 'command_chain': [ \ {'callback': 'ale#c#GetMakeCommand', 'output_stream': 'stdout'}, \ {'callback': 'ale_linters#cpp#clang#GetCommand'}, \ ], -\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', +\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes', \}) diff --git a/ale_linters/cpp/clangcheck.vim b/ale_linters/cpp/clangcheck.vim index a109d5d3..c66d6702 100644 --- a/ale_linters/cpp/clangcheck.vim +++ b/ale_linters/cpp/clangcheck.vim @@ -5,10 +5,6 @@ call ale#Set('cpp_clangcheck_executable', 'clang-check') call ale#Set('cpp_clangcheck_options', '') call ale#Set('c_build_dir', '') -function! ale_linters#cpp#clangcheck#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'cpp_clangcheck_executable') -endfunction - function! ale_linters#cpp#clangcheck#GetCommand(buffer) abort let l:user_options = ale#Var(a:buffer, 'cpp_clangcheck_options') @@ -16,23 +12,22 @@ function! ale_linters#cpp#clangcheck#GetCommand(buffer) abort let l:build_dir = ale#Var(a:buffer, 'c_build_dir') if empty(l:build_dir) - let l:build_dir = ale#c#FindCompileCommands(a:buffer) + let l:build_dir = ale#path#Dirname(ale#c#FindCompileCommands(a:buffer)) endif " The extra arguments in the command are used to prevent .plist files from " being generated. These are only added if no build directory can be " detected. - return ale#Escape(ale_linters#cpp#clangcheck#GetExecutable(a:buffer)) - \ . ' -analyze %s' + return '%e -analyze %s' \ . (empty(l:build_dir) ? ' -extra-arg -Xclang -extra-arg -analyzer-output=text' : '') - \ . (!empty(l:user_options) ? ' ' . l:user_options : '') + \ . ale#Pad(l:user_options) \ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '') endfunction call ale#linter#Define('cpp', { \ 'name': 'clangcheck', \ 'output_stream': 'stderr', -\ 'executable_callback': 'ale_linters#cpp#clangcheck#GetExecutable', +\ 'executable_callback': ale#VarFunc('cpp_clangcheck_executable'), \ 'command_callback': 'ale_linters#cpp#clangcheck#GetCommand', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'lint_file': 1, diff --git a/ale_linters/cpp/clangd.vim b/ale_linters/cpp/clangd.vim new file mode 100644 index 00000000..9139f054 --- /dev/null +++ b/ale_linters/cpp/clangd.vim @@ -0,0 +1,23 @@ +" Author: Andrey Melentyev <andrey.melentyev@protonmail.com> +" Description: Clangd language server + +call ale#Set('cpp_clangd_executable', 'clangd') +call ale#Set('cpp_clangd_options', '') + +function! ale_linters#cpp#clangd#GetProjectRoot(buffer) abort + let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json') + + return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' +endfunction + +function! ale_linters#cpp#clangd#GetCommand(buffer) abort + return '%e' . ale#Pad(ale#Var(a:buffer, 'cpp_clangd_options')) +endfunction + +call ale#linter#Define('cpp', { +\ 'name': 'clangd', +\ 'lsp': 'stdio', +\ 'executable_callback': ale#VarFunc('cpp_clangd_executable'), +\ 'command_callback': 'ale_linters#cpp#clangd#GetCommand', +\ 'project_root_callback': 'ale_linters#cpp#clangd#GetProjectRoot', +\}) diff --git a/ale_linters/cpp/clangtidy.vim b/ale_linters/cpp/clangtidy.vim index 1d5fb77a..9c3da8db 100644 --- a/ale_linters/cpp/clangtidy.vim +++ b/ale_linters/cpp/clangtidy.vim @@ -4,44 +4,22 @@ call ale#Set('cpp_clangtidy_executable', 'clang-tidy') " 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. " This will disable compile_commands.json detection. call ale#Set('cpp_clangtidy_options', '') call ale#Set('c_build_dir', '') -function! ale_linters#cpp#clangtidy#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'cpp_clangtidy_executable') -endfunction - -function! s:GetBuildDirectory(buffer) abort - " Don't include build directory for header files, as compile_commands.json - " files don't consider headers to be translation units, and provide no - " commands for compiling header files. - if expand('#' . a:buffer) =~# '\v\.(h|hpp)$' - return '' - endif - - let l:build_dir = ale#Var(a:buffer, 'c_build_dir') - - " c_build_dir has the priority if defined - if !empty(l:build_dir) - return l:build_dir - endif - - return ale#c#FindCompileCommands(a:buffer) -endfunction - function! ale_linters#cpp#clangtidy#GetCommand(buffer) abort let l:checks = join(ale#Var(a:buffer, 'cpp_clangtidy_checks'), ',') - let l:build_dir = s:GetBuildDirectory(a:buffer) + let l:build_dir = ale#c#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)) + return '%e' \ . (!empty(l:checks) ? ' -checks=' . ale#Escape(l:checks) : '') \ . ' %s' \ . (!empty(l:build_dir) ? ' -p ' . ale#Escape(l:build_dir) : '') @@ -51,7 +29,7 @@ endfunction call ale#linter#Define('cpp', { \ 'name': 'clangtidy', \ 'output_stream': 'stdout', -\ 'executable_callback': 'ale_linters#cpp#clangtidy#GetExecutable', +\ 'executable_callback': ale#VarFunc('cpp_clangtidy_executable'), \ 'command_callback': 'ale_linters#cpp#clangtidy#GetCommand', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \ 'lint_file': 1, diff --git a/ale_linters/cpp/clazy.vim b/ale_linters/cpp/clazy.vim new file mode 100644 index 00000000..cbbd0ccf --- /dev/null +++ b/ale_linters/cpp/clazy.vim @@ -0,0 +1,32 @@ +" 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_callback': ale#VarFunc('cpp_clazy_executable'), +\ 'command_callback': 'ale_linters#cpp#clazy#GetCommand', +\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', +\ 'lint_file': 1, +\}) diff --git a/ale_linters/cpp/cppcheck.vim b/ale_linters/cpp/cppcheck.vim index 8b2aa802..229d6133 100644 --- a/ale_linters/cpp/cppcheck.vim +++ b/ale_linters/cpp/cppcheck.vim @@ -4,10 +4,6 @@ call ale#Set('cpp_cppcheck_executable', 'cppcheck') 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 " Search upwards from the file for compile_commands.json. " @@ -23,8 +19,7 @@ function! ale_linters#cpp#cppcheck#GetCommand(buffer) abort \ : '' return l:cd_command - \ . ale#Escape(ale_linters#cpp#cppcheck#GetExecutable(a:buffer)) - \ . ' -q --language=c++ ' + \ . '%e -q --language=c++ ' \ . l:compile_commands_option \ . ale#Var(a:buffer, 'cpp_cppcheck_options') \ . ' %t' @@ -33,7 +28,7 @@ endfunction call ale#linter#Define('cpp', { \ 'name': 'cppcheck', \ 'output_stream': 'both', -\ 'executable_callback': 'ale_linters#cpp#cppcheck#GetExecutable', +\ 'executable_callback': ale#VarFunc('cpp_cppcheck_executable'), \ 'command_callback': 'ale_linters#cpp#cppcheck#GetCommand', \ 'callback': 'ale#handlers#cppcheck#HandleCppCheckFormat', \}) diff --git a/ale_linters/cpp/cpplint.vim b/ale_linters/cpp/cpplint.vim index 346ac815..d135fa79 100644 --- a/ale_linters/cpp/cpplint.vim +++ b/ale_linters/cpp/cpplint.vim @@ -4,22 +4,16 @@ call ale#Set('cpp_cpplint_executable', 'cpplint') call ale#Set('cpp_cpplint_options', '') -function! ale_linters#cpp#cpplint#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'cpp_cpplint_executable') -endfunction - function! ale_linters#cpp#cpplint#GetCommand(buffer) abort let l:options = ale#Var(a:buffer, 'cpp_cpplint_options') - return ale#Escape(ale_linters#cpp#cpplint#GetExecutable(a:buffer)) - \ . (!empty(l:options) ? ' ' . l:options : '') - \ . ' %s' + return '%e' . ale#Pad(l:options) . ' %s' endfunction call ale#linter#Define('cpp', { \ 'name': 'cpplint', \ 'output_stream': 'stderr', -\ 'executable_callback': 'ale_linters#cpp#cpplint#GetExecutable', +\ 'executable_callback': ale#VarFunc('cpp_cpplint_executable'), \ 'command_callback': 'ale_linters#cpp#cpplint#GetCommand', \ 'callback': 'ale#handlers#cpplint#HandleCppLintFormat', \ 'lint_file': 1, diff --git a/ale_linters/cpp/cquery.vim b/ale_linters/cpp/cquery.vim index 7997c843..b1c81989 100644 --- a/ale_linters/cpp/cquery.vim +++ b/ale_linters/cpp/cquery.vim @@ -7,16 +7,11 @@ call ale#Set('cpp_cquery_cache_directory', expand('~/.cache/cquery')) function! ale_linters#cpp#cquery#GetProjectRoot(buffer) abort let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json') - return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' -endfunction + if empty(l:project_root) + let l:project_root = ale#path#FindNearestFile(a:buffer, '.cquery') + endif -function! ale_linters#cpp#cquery#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'cpp_cquery_executable') -endfunction - -function! ale_linters#cpp#cquery#GetCommand(buffer) abort - let l:executable = ale_linters#cpp#cquery#GetExecutable(a:buffer) - return ale#Escape(l:executable) + return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' endfunction function! ale_linters#cpp#cquery#GetInitializationOptions(buffer) abort @@ -26,8 +21,8 @@ endfunction call ale#linter#Define('cpp', { \ 'name': 'cquery', \ 'lsp': 'stdio', -\ 'executable_callback': 'ale_linters#cpp#cquery#GetExecutable', -\ 'command_callback': 'ale_linters#cpp#cquery#GetCommand', +\ 'executable_callback': ale#VarFunc('cpp_cquery_executable'), +\ 'command': '%e', \ 'project_root_callback': 'ale_linters#cpp#cquery#GetProjectRoot', \ 'initialization_options_callback': 'ale_linters#cpp#cquery#GetInitializationOptions', \}) diff --git a/ale_linters/cpp/flawfinder.vim b/ale_linters/cpp/flawfinder.vim index 5a7092cf..4f669bff 100644 --- a/ale_linters/cpp/flawfinder.vim +++ b/ale_linters/cpp/flawfinder.vim @@ -6,17 +6,11 @@ call ale#Set('cpp_flawfinder_options', '') call ale#Set('cpp_flawfinder_minlevel', 1) call ale#Set('c_flawfinder_error_severity', 6) -function! ale_linters#cpp#flawfinder#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'cpp_flawfinder_executable') -endfunction - function! ale_linters#cpp#flawfinder#GetCommand(buffer) abort - " Set the minimum vulnerability level for flawfinder to bother with let l:minlevel = ' --minlevel=' . ale#Var(a:buffer, 'cpp_flawfinder_minlevel') - return ale#Escape(ale_linters#cpp#flawfinder#GetExecutable(a:buffer)) - \ . ' -CDQS' + return '%e -CDQS' \ . ale#Var(a:buffer, 'cpp_flawfinder_options') \ . l:minlevel \ . ' %t' @@ -25,7 +19,7 @@ endfunction call ale#linter#Define('cpp', { \ 'name': 'flawfinder', \ 'output_stream': 'stdout', -\ 'executable_callback': 'ale_linters#cpp#flawfinder#GetExecutable', +\ 'executable_callback': ale#VarFunc('cpp_flawfinder_executable'), \ 'command_callback': 'ale_linters#cpp#flawfinder#GetCommand', \ 'callback': 'ale#handlers#flawfinder#HandleFlawfinderFormat', \}) diff --git a/ale_linters/cpp/gcc.vim b/ale_linters/cpp/gcc.vim index a663eaa3..9935b0bb 100644 --- a/ale_linters/cpp/gcc.vim +++ b/ale_linters/cpp/gcc.vim @@ -4,30 +4,25 @@ call ale#Set('cpp_gcc_executable', 'gcc') call ale#Set('cpp_gcc_options', '-std=c++14 -Wall') -function! ale_linters#cpp#gcc#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'cpp_gcc_executable') -endfunction - function! ale_linters#cpp#gcc#GetCommand(buffer, output) abort let l:cflags = ale#c#GetCFlags(a:buffer, a:output) " -iquote with the directory the file is in makes #include work for " headers in the same directory. - return ale#Escape(ale_linters#cpp#gcc#GetExecutable(a:buffer)) - \ . ' -S -x c++ -fsyntax-only ' - \ . '-iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) . ' ' - \ . l:cflags - \ . ale#Var(a:buffer, 'cpp_gcc_options') . ' -' + return '%e -S -x c++ -fsyntax-only' + \ . ' -iquote ' . ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) + \ . ale#Pad(l:cflags) + \ . ale#Pad(ale#Var(a:buffer, 'cpp_gcc_options')) . ' -' endfunction call ale#linter#Define('cpp', { \ 'name': 'gcc', \ 'aliases': ['g++'], \ 'output_stream': 'stderr', -\ 'executable_callback': 'ale_linters#cpp#gcc#GetExecutable', +\ 'executable_callback': ale#VarFunc('cpp_gcc_executable'), \ 'command_chain': [ \ {'callback': 'ale#c#GetMakeCommand', 'output_stream': 'stdout'}, \ {'callback': 'ale_linters#cpp#gcc#GetCommand'}, \ ], -\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', +\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes', \}) diff --git a/ale_linters/css/stylelint.vim b/ale_linters/css/stylelint.vim index a16dfde2..6f8bef68 100644 --- a/ale_linters/css/stylelint.vim +++ b/ale_linters/css/stylelint.vim @@ -4,21 +4,16 @@ call ale#Set('css_stylelint_executable', 'stylelint') call ale#Set('css_stylelint_options', '') call ale#Set('css_stylelint_use_global', get(g:, 'ale_use_global_executables', 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 - return ale_linters#css#stylelint#GetExecutable(a:buffer) - \ . ' ' . ale#Var(a:buffer, 'css_stylelint_options') + return '%e ' . ale#Pad(ale#Var(a:buffer, 'css_stylelint_options')) \ . ' --stdin-filename %s' endfunction call ale#linter#Define('css', { \ 'name': 'stylelint', -\ 'executable_callback': 'ale_linters#css#stylelint#GetExecutable', +\ 'executable_callback': ale#node#FindExecutableFunc('css_stylelint', [ +\ 'node_modules/.bin/stylelint', +\ ]), \ 'command_callback': 'ale_linters#css#stylelint#GetCommand', \ 'callback': 'ale#handlers#css#HandleStyleLintFormat', \}) diff --git a/ale_linters/cucumber/cucumber.vim b/ale_linters/cucumber/cucumber.vim index 6708d32f..e8ae09ff 100644 --- a/ale_linters/cucumber/cucumber.vim +++ b/ale_linters/cucumber/cucumber.vim @@ -22,6 +22,7 @@ function! ale_linters#cucumber#cucumber#Handle(buffer, lines) abort 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' diff --git a/ale_linters/cuda/nvcc.vim b/ale_linters/cuda/nvcc.vim index 3764fe9d..f4442cb8 100644 --- a/ale_linters/cuda/nvcc.vim +++ b/ale_linters/cuda/nvcc.vim @@ -4,20 +4,14 @@ call ale#Set('cuda_nvcc_executable', 'nvcc') 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 " Unused: use ale#util#nul_file " let l:output_file = ale#util#Tempname() . '.ii' " call ale#engine#ManageFile(a:buffer, l:output_file) - - return ale#Escape(ale_linters#cuda#nvcc#GetExecutable(a:buffer)) - \ . ' -cuda ' - \ . ale#c#IncludeOptions(ale#c#FindLocalHeaderPaths(a:buffer)) - \ . ale#Var(a:buffer, 'cuda_nvcc_options') . ' %s' - \ . ' -o ' . g:ale#util#nul_file + return '%e -cuda' + \ . ale#Pad(ale#c#IncludeOptions(ale#c#FindLocalHeaderPaths(a:buffer))) + \ . ale#Pad(ale#Var(a:buffer, 'cuda_nvcc_options')) + \ . ' %s -o ' . g:ale#util#nul_file endfunction function! ale_linters#cuda#nvcc#HandleNVCCFormat(buffer, lines) abort @@ -28,7 +22,6 @@ function! ale_linters#cuda#nvcc#HandleNVCCFormat(buffer, lines) abort let l:output = [] for l:match in ale#util#GetMatches(a:lines, l:pattern) - let l:item = { \ 'lnum': str2nr(l:match[2]), \ 'type': l:match[4] =~# 'error' ? 'E' : 'W', @@ -49,7 +42,7 @@ endfunction call ale#linter#Define('cuda', { \ 'name': 'nvcc', \ 'output_stream': 'stderr', -\ 'executable_callback': 'ale_linters#cuda#nvcc#GetExecutable', +\ 'executable_callback': ale#VarFunc('cuda_nvcc_executable'), \ 'command_callback': 'ale_linters#cuda#nvcc#GetCommand', \ 'callback': 'ale_linters#cuda#nvcc#HandleNVCCFormat', \ 'lint_file': 1, diff --git a/ale_linters/d/dls.vim b/ale_linters/d/dls.vim new file mode 100644 index 00000000..7210d21e --- /dev/null +++ b/ale_linters/d/dls.vim @@ -0,0 +1,22 @@ +" 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_callback': 'ale_linters#d#dls#GetExecutable', +\ 'command_callback': 'ale_linters#d#dls#GetExecutable', +\ 'project_root_callback': 'ale_linters#d#dls#FindProjectRoot', +\}) diff --git a/ale_linters/d/dmd.vim b/ale_linters/d/dmd.vim index d64b6c3d..c816d592 100644 --- a/ale_linters/d/dmd.vim +++ b/ale_linters/d/dmd.vim @@ -1,20 +1,6 @@ " Author: w0rp <devw0rp@gmail.com> " Description: "dmd for D files" -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 !executable('dub') @@ -22,7 +8,7 @@ function! ale_linters#d#dmd#DUBCommand(buffer) abort return '' endif - let l:dub_file = s:FindDUBConfig(a:buffer) + let l:dub_file = ale#d#FindDUBConfig(a:buffer) if empty(l:dub_file) return '' diff --git a/ale_linters/dafny/dafny.vim b/ale_linters/dafny/dafny.vim index 8bbf1b13..b5b90675 100644 --- a/ale_linters/dafny/dafny.vim +++ b/ale_linters/dafny/dafny.vim @@ -13,6 +13,7 @@ function! ale_linters#dafny#dafny#Handle(buffer, lines) abort \ 'type': l:match[4] =~# '^Error' ? 'E' : 'W' \ }) endfor + return l:output endfunction diff --git a/ale_linters/dart/dartanalyzer.vim b/ale_linters/dart/dartanalyzer.vim index ef33c9d4..26817df5 100644 --- a/ale_linters/dart/dartanalyzer.vim +++ b/ale_linters/dart/dartanalyzer.vim @@ -3,15 +3,10 @@ call ale#Set('dart_dartanalyzer_executable', 'dartanalyzer') -function! ale_linters#dart#dartanalyzer#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'dart_dartanalyzer_executable') -endfunction - function! ale_linters#dart#dartanalyzer#GetCommand(buffer) abort - let l:executable = ale_linters#dart#dartanalyzer#GetExecutable(a:buffer) let l:path = ale#path#FindNearestFile(a:buffer, '.packages') - return ale#Escape(l:executable) + return '%e' \ . (!empty(l:path) ? ' --packages ' . ale#Escape(l:path) : '') \ . ' %s' endfunction @@ -34,7 +29,7 @@ endfunction call ale#linter#Define('dart', { \ 'name': 'dartanalyzer', -\ 'executable_callback': 'ale_linters#dart#dartanalyzer#GetExecutable', +\ 'executable_callback': ale#VarFunc('dart_dartanalyzer_executable'), \ 'command_callback': 'ale_linters#dart#dartanalyzer#GetCommand', \ 'callback': 'ale_linters#dart#dartanalyzer#Handle', \ 'lint_file': 1, diff --git a/ale_linters/dart/language_server.vim b/ale_linters/dart/language_server.vim index 2265e37a..8e0c139b 100644 --- a/ale_linters/dart/language_server.vim +++ b/ale_linters/dart/language_server.vim @@ -3,10 +3,6 @@ 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#GetProjectRoot(buffer) abort " Note: pub only looks for pubspec.yaml, there's no point in adding " support for pubspec.yml @@ -18,7 +14,7 @@ endfunction call ale#linter#Define('dart', { \ 'name': 'language_server', \ 'lsp': 'stdio', -\ 'executable_callback': 'ale_linters#dart#language_server#GetExecutable', -\ 'command_callback': 'ale_linters#dart#language_server#GetExecutable', +\ 'executable_callback': ale#VarFunc('dart_language_server_executable'), +\ 'command': '%e', \ 'project_root_callback': 'ale_linters#dart#language_server#GetProjectRoot', \}) diff --git a/ale_linters/dockerfile/dockerfile_lint.vim b/ale_linters/dockerfile/dockerfile_lint.vim new file mode 100644 index 00000000..a5a846f2 --- /dev/null +++ b/ale_linters/dockerfile/dockerfile_lint.vim @@ -0,0 +1,61 @@ +" 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_callback': ale#VarFunc('dockerfile_dockerfile_lint_executable'), +\ 'command_callback': 'ale_linters#dockerfile#dockerfile_lint#GetCommand', +\ 'callback': 'ale_linters#dockerfile#dockerfile_lint#Handle', +\}) diff --git a/ale_linters/dockerfile/hadolint.vim b/ale_linters/dockerfile/hadolint.vim index 7772afbd..dc0f5b9e 100644 --- a/ale_linters/dockerfile/hadolint.vim +++ b/ale_linters/dockerfile/hadolint.vim @@ -82,9 +82,11 @@ endfunction function! ale_linters#dockerfile#hadolint#GetCommand(buffer) abort let l:command = ale_linters#dockerfile#hadolint#GetExecutable(a:buffer) + if l:command is# 'docker' return 'docker run --rm -i ' . ale#Var(a:buffer, 'dockerfile_hadolint_docker_image') endif + return 'hadolint -' endfunction diff --git a/ale_linters/elixir/credo.vim b/ale_linters/elixir/credo.vim index af2ff48a..d778471c 100644 --- a/ale_linters/elixir/credo.vim +++ b/ale_linters/elixir/credo.vim @@ -11,10 +11,18 @@ function! ale_linters#elixir#credo#Handle(buffer, lines) abort let l:type = l:match[3] let l:text = l:match[4] - if l:type is# 'C' - let l:type = 'E' - elseif l:type is# 'R' + " Refactoring opportunities + if l:type is# 'F' + 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' + let l:type = 'I' endif call add(l:output, { @@ -29,9 +37,16 @@ function! ale_linters#elixir#credo#Handle(buffer, lines) abort return l:output endfunction +function! ale_linters#elixir#credo#GetCommand(buffer) abort + let l:project_root = ale#handlers#elixir#FindMixProjectRoot(a:buffer) + + return ale#path#CdString(l:project_root) + \ . ' mix help credo && mix credo suggest --format=flycheck --read-from-stdin %s' +endfunction + call ale#linter#Define('elixir', { \ 'name': 'credo', \ 'executable': 'mix', -\ 'command': 'mix help credo && mix credo suggest --format=flycheck --read-from-stdin %s', +\ 'command_callback': 'ale_linters#elixir#credo#GetCommand', \ 'callback': 'ale_linters#elixir#credo#Handle', \}) diff --git a/ale_linters/elixir/dialyxir.vim b/ale_linters/elixir/dialyxir.vim index bba0ae14..d28d3c70 100644 --- a/ale_linters/elixir/dialyxir.vim +++ b/ale_linters/elixir/dialyxir.vim @@ -25,10 +25,17 @@ function! ale_linters#elixir#dialyxir#Handle(buffer, lines) abort return l:output 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', { \ 'name': 'dialyxir', \ 'executable': 'mix', -\ 'command': 'mix help dialyzer && mix dialyzer', +\ 'command_callback': 'ale_linters#elixir#dialyxir#GetCommand', \ 'callback': 'ale_linters#elixir#dialyxir#Handle', \}) diff --git a/ale_linters/elixir/dogma.vim b/ale_linters/elixir/dogma.vim index 71cf4f4c..dcfb6f28 100644 --- a/ale_linters/elixir/dogma.vim +++ b/ale_linters/elixir/dogma.vim @@ -29,10 +29,17 @@ function! ale_linters#elixir#dogma#Handle(buffer, lines) abort return l:output 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', { \ 'name': 'dogma', \ 'executable': 'mix', -\ 'command': 'mix help dogma && mix dogma %s --format=flycheck', +\ 'command_callback': 'ale_linters#elixir#dogma#GetCommand', \ 'lint_file': 1, \ 'callback': 'ale_linters#elixir#dogma#Handle', \}) diff --git a/ale_linters/elixir/elixir_ls.vim b/ale_linters/elixir/elixir_ls.vim new file mode 100644 index 00000000..3b299ec6 --- /dev/null +++ b/ale_linters/elixir/elixir_ls.vim @@ -0,0 +1,21 @@ +" 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 = ale#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_callback': 'ale_linters#elixir#elixir_ls#GetExecutable', +\ 'command_callback': 'ale_linters#elixir#elixir_ls#GetExecutable', +\ 'project_root_callback': 'ale#handlers#elixir#FindMixUmbrellaRoot', +\ 'lsp_config_callback': ale#VarFunc('elixir_elixir_ls_config'), +\}) diff --git a/ale_linters/elixir/mix.vim b/ale_linters/elixir/mix.vim index 1a95e37f..dc3c1818 100644 --- a/ale_linters/elixir/mix.vim +++ b/ale_linters/elixir/mix.vim @@ -10,7 +10,6 @@ function! ale_linters#elixir#mix#Handle(buffer, lines) abort " " 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 = [] @@ -30,16 +29,8 @@ function! ale_linters#elixir#mix#Handle(buffer, lines) abort return l:output endfunction -function! ale_linters#elixir#mix#FindProjectRoot(buffer) abort - let l:mix_file = ale#path#FindNearestFile(a:buffer, 'mix.exs') - if !empty(l:mix_file) - return fnamemodify(l:mix_file, ':p:h') - endif - return '.' -endfunction - function! ale_linters#elixir#mix#GetCommand(buffer) abort - let l:project_root = ale_linters#elixir#mix#FindProjectRoot(a:buffer) + let l:project_root = ale#handlers#elixir#FindMixProjectRoot(a:buffer) let l:temp_dir = ale#engine#CreateDirectory(a:buffer) @@ -48,8 +39,8 @@ function! ale_linters#elixir#mix#GetCommand(buffer) abort \ : 'MIX_BUILD_PATH=' . ale#Escape(l:temp_dir) return ale#path#CdString(l:project_root) - \ . l:mix_build_path - \ . ' mix compile %s' + \ . l:mix_build_path + \ . ' mix compile %s' endfunction call ale#linter#Define('elixir', { diff --git a/ale_linters/elm/make.vim b/ale_linters/elm/make.vim index d5bc19eb..ddea983f 100644 --- a/ale_linters/elm/make.vim +++ b/ale_linters/elm/make.vim @@ -4,12 +4,6 @@ call ale#Set('elm_make_executable', 'elm') call ale#Set('elm_make_use_global', get(g:, 'ale_use_global_executables', 0)) -function! ale_linters#elm#make#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'elm_make', [ - \ 'node_modules/.bin/elm', - \]) -endfunction - function! ale_linters#elm#make#Handle(buffer, lines) abort let l:output = [] let l:unparsed_lines = [] @@ -136,7 +130,7 @@ function! ale_linters#elm#make#ParseMessage(message) abort endfunction function! ale_linters#elm#make#ParseMessageItem(item) abort - if type(a:item) == type('') + if type(a:item) is v:t_string return a:item else return a:item.string @@ -147,7 +141,6 @@ endfunction " If it doesn't, then this will fail when imports are needed. function! ale_linters#elm#make#GetCommand(buffer) abort let l:elm_json = ale#path#FindNearestFile(a:buffer, 'elm.json') - let l:elm_exe = ale_linters#elm#make#GetExecutable(a:buffer) if empty(l:elm_json) " Fallback to Elm 0.18 @@ -165,18 +158,15 @@ function! ale_linters#elm#make#GetCommand(buffer) abort " a sort of flag to tell the compiler not to generate an output file, " which is why this is hard coded here. " Source: https://github.com/elm-lang/elm-compiler/blob/19d5a769b30ec0b2fc4475985abb4cd94cd1d6c3/builder/src/Generate/Output.hs#L253 - let l:elm_cmd = ale#Escape(l:elm_exe) - \ . ' make' - \ . ' --report=json' - \ . ' --output=/dev/null' - - return l:dir_set_cmd . ' ' . l:elm_cmd . ' %t' + return l:dir_set_cmd . '%e make --report=json --output=/dev/null %t' endfunction call ale#linter#Define('elm', { -\ 'name': 'make', -\ 'executable_callback': 'ale_linters#elm#make#GetExecutable', -\ 'output_stream': 'both', -\ 'command_callback': 'ale_linters#elm#make#GetCommand', -\ 'callback': 'ale_linters#elm#make#Handle' +\ 'name': 'make', +\ 'executable_callback': ale#node#FindExecutableFunc('elm_make', [ +\ 'node_modules/.bin/elm', +\ ]), +\ 'output_stream': 'both', +\ 'command_callback': 'ale_linters#elm#make#GetCommand', +\ 'callback': 'ale_linters#elm#make#Handle' \}) diff --git a/ale_linters/erlang/syntaxerl.vim b/ale_linters/erlang/syntaxerl.vim index 46ecdcb7..5b679743 100644 --- a/ale_linters/erlang/syntaxerl.vim +++ b/ale_linters/erlang/syntaxerl.vim @@ -3,24 +3,12 @@ call ale#Set('erlang_syntaxerl_executable', 'syntaxerl') - -function! ale_linters#erlang#syntaxerl#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'erlang_syntaxerl_executable') -endfunction - - -function! ale_linters#erlang#syntaxerl#FeatureCheck(buffer) abort - return s:GetEscapedExecutable(a:buffer) . ' -h' -endfunction - - function! ale_linters#erlang#syntaxerl#GetCommand(buffer, output) abort let l:use_b_option = match(a:output, '\C\V-b, --base\>') > -1 - return s:GetEscapedExecutable(a:buffer) . (l:use_b_option ? ' -b %s %t' : ' %t') + return '%e' . (l:use_b_option ? ' -b %s %t' : ' %t') endfunction - function! ale_linters#erlang#syntaxerl#Handle(buffer, lines) abort let l:pattern = '\v\C:(\d+):( warning:)? (.+)' let l:loclist = [] @@ -36,17 +24,11 @@ function! ale_linters#erlang#syntaxerl#Handle(buffer, lines) abort return l:loclist endfunction - -function! s:GetEscapedExecutable(buffer) abort - return ale#Escape(ale_linters#erlang#syntaxerl#GetExecutable(a:buffer)) -endfunction - - call ale#linter#Define('erlang', { \ 'name': 'syntaxerl', -\ 'executable_callback': 'ale_linters#erlang#syntaxerl#GetExecutable', +\ 'executable_callback': ale#VarFunc('erlang_syntaxerl_executable'), \ 'command_chain': [ -\ {'callback': 'ale_linters#erlang#syntaxerl#FeatureCheck'}, +\ {'callback': {-> '%e -h'}}, \ {'callback': 'ale_linters#erlang#syntaxerl#GetCommand'}, \ ], \ 'callback': 'ale_linters#erlang#syntaxerl#Handle', diff --git a/ale_linters/eruby/ruumba.vim b/ale_linters/eruby/ruumba.vim new file mode 100644 index 00000000..24f112e4 --- /dev/null +++ b/ale_linters/eruby/ruumba.vim @@ -0,0 +1,62 @@ +" 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#handlers#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_callback': ale#VarFunc('eruby_ruumba_executable'), +\ 'command_callback': 'ale_linters#eruby#ruumba#GetCommand', +\ 'callback': 'ale_linters#eruby#ruumba#Handle', +\}) diff --git a/ale_linters/fortran/gcc.vim b/ale_linters/fortran/gcc.vim index 5f2ac018..f1595789 100644 --- a/ale_linters/fortran/gcc.vim +++ b/ale_linters/fortran/gcc.vim @@ -2,18 +2,10 @@ " Description: gcc for Fortran files " This option can be set to 0 to use -ffixed-form -if !exists('g:ale_fortran_gcc_use_free_form') - let g:ale_fortran_gcc_use_free_form = 1 -endif - -if !exists('g:ale_fortran_gcc_executable') - let g:ale_fortran_gcc_executable = 'gcc' -endif - +call ale#Set('fortran_gcc_use_free_form', 1) +call ale#Set('fortran_gcc_executable', 'gcc') " Set this option to change the GCC options for warnings for Fortran. -if !exists('g:ale_fortran_gcc_options') - let g:ale_fortran_gcc_options = '-Wall' -endif +call ale#Set('fortran_gcc_options', '-Wall') function! ale_linters#fortran#gcc#Handle(buffer, lines) abort " We have to match a starting line and a later ending line together, @@ -61,26 +53,20 @@ function! ale_linters#fortran#gcc#Handle(buffer, lines) abort return l:output endfunction -function! ale_linters#fortran#gcc#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'fortran_gcc_executable') -endfunction - function! ale_linters#fortran#gcc#GetCommand(buffer) abort let l:layout_option = ale#Var(a:buffer, 'fortran_gcc_use_free_form') \ ? '-ffree-form' \ : '-ffixed-form' - return ale_linters#fortran#gcc#GetExecutable(a:buffer) - \ . ' -S -x f95 -fsyntax-only ' - \ . l:layout_option . ' ' - \ . ale#Var(a:buffer, 'fortran_gcc_options') . ' ' - \ . '-' + return '%e -S -x f95 -fsyntax-only ' . l:layout_option + \ . ale#Pad(ale#Var(a:buffer, 'fortran_gcc_options')) + \ . ' -' endfunction call ale#linter#Define('fortran', { \ 'name': 'gcc', \ 'output_stream': 'stderr', -\ 'executable_callback': 'ale_linters#fortran#gcc#GetExecutable', +\ 'executable_callback': ale#VarFunc('fortran_gcc_executable'), \ 'command_callback': 'ale_linters#fortran#gcc#GetCommand', \ 'callback': 'ale_linters#fortran#gcc#Handle', \}) diff --git a/ale_linters/fortran/language_server.vim b/ale_linters/fortran/language_server.vim index fd763fcf..4e5f5dc4 100644 --- a/ale_linters/fortran/language_server.vim +++ b/ale_linters/fortran/language_server.vim @@ -4,14 +4,6 @@ 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#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'fortran_language_server_executable') -endfunction - -function! ale_linters#fortran#language_server#GetCommand(buffer) abort - return ale#Escape(ale_linters#fortran#language_server#GetExecutable(a:buffer)) -endfunction - function! ale_linters#fortran#language_server#GetProjectRoot(buffer) abort let l:fortls_file = ale#path#FindNearestFile(a:buffer, '.fortls') @@ -21,7 +13,7 @@ endfunction call ale#linter#Define('fortran', { \ 'name': 'language_server', \ 'lsp': 'stdio', -\ 'executable_callback': 'ale_linters#fortran#language_server#GetExecutable', -\ 'command_callback': 'ale_linters#fortran#language_server#GetCommand', +\ 'executable_callback': ale#VarFunc('fortran_language_server_executable'), +\ 'command': '%e', \ 'project_root_callback': 'ale_linters#fortran#language_server#GetProjectRoot', \}) diff --git a/ale_linters/fuse/fusionlint.vim b/ale_linters/fuse/fusionlint.vim index cf20e1b4..ab8f143b 100644 --- a/ale_linters/fuse/fusionlint.vim +++ b/ale_linters/fuse/fusionlint.vim @@ -4,13 +4,8 @@ call ale#Set('fuse_fusionlint_executable', 'fusion-lint') call ale#Set('fuse_fusionlint_options', '') -function! ale_linters#fuse#fusionlint#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'fuse_fusionlint_executable') -endfunction - function! ale_linters#fuse#fusionlint#GetCommand(buffer) abort - return ale#Escape(ale_linters#fuse#fusionlint#GetExecutable(a:buffer)) - \ . ale#Pad(ale#Var(a:buffer, 'fuse_fusionlint_options')) + return '%e' . ale#Pad(ale#Var(a:buffer, 'fuse_fusionlint_options')) \ . ' --filename %s -i' endfunction @@ -32,7 +27,7 @@ endfunction call ale#linter#Define('fuse', { \ 'name': 'fusionlint', -\ 'executable_callback': 'ale_linters#fuse#fusionlint#GetExecutable', +\ 'executable_callback': ale#VarFunc('fuse_fusionlint_executable'), \ 'command_callback': 'ale_linters#fuse#fusionlint#GetCommand', \ 'callback': 'ale_linters#fuse#fusionlint#Handle', \}) diff --git a/ale_linters/gitcommit/gitlint.vim b/ale_linters/gitcommit/gitlint.vim index 64731055..a9c4822d 100644 --- a/ale_linters/gitcommit/gitlint.vim +++ b/ale_linters/gitcommit/gitlint.vim @@ -1,11 +1,9 @@ " Author: Nick Yamane <nick.diego@gmail.com> " Description: gitlint for git commit message files -let g:ale_gitcommit_gitlint_executable = -\ get(g:, 'ale_gitcommit_gitlint_executable', 'gitlint') -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', get(g:, 'ale_use_global_executables', 0)) - +call ale#Set('gitcommit_gitlint_executable', 'gitlint') +call ale#Set('gitcommit_gitlint_options', '') +call ale#Set('gitcommit_gitlint_use_global', get(g:, 'ale_use_global_executables', 0)) function! ale_linters#gitcommit#gitlint#GetExecutable(buffer) abort return ale#python#FindExecutable(a:buffer, 'gitcommit_gitlint', ['gitlint']) @@ -13,12 +11,9 @@ endfunction function! ale_linters#gitcommit#gitlint#GetCommand(buffer) abort let l:options = ale#Var(a:buffer, 'gitcommit_gitlint_options') - let l:executable = ale_linters#gitcommit#gitlint#GetExecutable(a:buffer) - return ale#Escape(l:executable) - \ . (!empty(l:options) ? ' ' . l:options : '') - \ . ' lint' -endfunction + return '%e' . ale#Pad(l:options) . ' lint' +endfunction function! ale_linters#gitcommit#gitlint#Handle(buffer, lines) abort " Matches patterns line the following: @@ -28,8 +23,10 @@ function! ale_linters#gitcommit#gitlint#Handle(buffer, lines) abort for l:match in ale#util#GetMatches(a:lines, l:pattern) let l:code = l:match[2] - if l:code is# 'T2' && !ale#Var(a:buffer, 'warn_about_trailing_whitespace') - continue + if !ale#Var(a:buffer, 'warn_about_trailing_whitespace') + if l:code is# 'T2' || l:code is# 'B2' + continue + endif endif let l:item = { @@ -45,7 +42,6 @@ function! ale_linters#gitcommit#gitlint#Handle(buffer, lines) abort return l:output endfunction - call ale#linter#Define('gitcommit', { \ 'name': 'gitlint', \ 'output_stream': 'stderr', @@ -53,4 +49,3 @@ call ale#linter#Define('gitcommit', { \ 'command_callback': 'ale_linters#gitcommit#gitlint#GetCommand', \ 'callback': 'ale_linters#gitcommit#gitlint#Handle', \}) - diff --git a/ale_linters/glsl/glslang.vim b/ale_linters/glsl/glslang.vim index d494df0e..d55a5e7c 100644 --- a/ale_linters/glsl/glslang.vim +++ b/ale_linters/glsl/glslang.vim @@ -4,17 +4,11 @@ " TODO: Once https://github.com/KhronosGroup/glslang/pull/1047 is accepted, " we can use stdin. -let g:ale_glsl_glslang_executable = -\ 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 +call ale#Set('glsl_glslang_executable', 'glslangValidator') +call ale#Set('glsl_glslang_options', '') function! ale_linters#glsl#glslang#GetCommand(buffer) abort - return ale#Escape(ale_linters#glsl#glslang#GetExecutable(a:buffer)) + return '%e' \ . ale#Pad(ale#Var(a:buffer, 'glsl_glslang_options')) \ . ' -C %t' endfunction @@ -40,7 +34,7 @@ endfunction call ale#linter#Define('glsl', { \ 'name': 'glslang', -\ 'executable_callback': 'ale_linters#glsl#glslang#GetExecutable', +\ 'executable_callback': ale#VarFunc('glsl_glslang_executable'), \ 'command_callback': 'ale_linters#glsl#glslang#GetCommand', \ 'callback': 'ale_linters#glsl#glslang#Handle', \}) diff --git a/ale_linters/glsl/glslls.vim b/ale_linters/glsl/glslls.vim index 77e30f9c..8c6d9bd9 100644 --- a/ale_linters/glsl/glslls.vim +++ b/ale_linters/glsl/glslls.vim @@ -4,18 +4,15 @@ call ale#Set('glsl_glslls_executable', 'glslls') 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 - let l:executable = ale_linters#glsl#glslls#GetExecutable(a:buffer) let l:logfile = ale#Var(a:buffer, 'glsl_glslls_logfile') let l:logfile_args = '' + if l:logfile isnot# '' let l:logfile_args = ' --verbose -l ' . l:logfile endif - return ale#Escape(l:executable) . l:logfile_args . ' --stdin' + + return '%e' . l:logfile_args . ' --stdin' endfunction function! ale_linters#glsl#glslls#GetProjectRoot(buffer) abort @@ -27,7 +24,7 @@ endfunction call ale#linter#Define('glsl', { \ 'name': 'glslls', \ 'lsp': 'stdio', -\ 'executable_callback': 'ale_linters#glsl#glslls#GetExecutable', +\ 'executable_callback': ale#VarFunc('glsl_glslls_executable'), \ 'command_callback': 'ale_linters#glsl#glslls#GetCommand', \ 'project_root_callback': 'ale_linters#glsl#glslls#GetProjectRoot', \}) diff --git a/ale_linters/go/gobuild.vim b/ale_linters/go/gobuild.vim index c4608071..cef1ff88 100644 --- a/ale_linters/go/gobuild.vim +++ b/ale_linters/go/gobuild.vim @@ -3,38 +3,15 @@ " Description: go build for Go files " inspired by work from dzhou121 <dzhou121@gmail.com> +call ale#Set('go_go_executable', 'go') call ale#Set('go_gobuild_options', '') -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 +function! ale_linters#go#gobuild#GetCommand(buffer) abort 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 - return l:gopath_env_command - \ . ale#path#BufferCdString(a:buffer) - \ . 'go test' + return ale#path#BufferCdString(a:buffer) + \ . ale#Var(a:buffer, 'go_go_executable') . ' test' \ . (!empty(l:options) ? ' ' . l:options : '') \ . ' -c -o /dev/null ./' endfunction @@ -45,7 +22,6 @@ 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:53:10: if block ends with a return statement, so drop this else and outdent its block (move short variable declaration to its own line if necessary) " file.go:5:2: expected declaration, found 'STRING' "log" - " go test returns relative paths so use tail of filename as part of pattern matcher let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+):?(\d+)?:? (.+)$' @@ -72,11 +48,9 @@ endfunction call ale#linter#Define('go', { \ 'name': 'gobuild', \ 'aliases': ['go build'], -\ 'executable': 'go', -\ 'command_chain': [ -\ {'callback': 'ale_linters#go#gobuild#GoEnv', 'output_stream': 'stdout'}, -\ {'callback': 'ale_linters#go#gobuild#GetCommand', 'output_stream': 'stderr'}, -\ ], +\ 'executable_callback': ale#VarFunc('go_go_executable'), +\ 'command_callback': 'ale_linters#go#gobuild#GetCommand', +\ 'output_stream': 'stderr', \ 'callback': 'ale_linters#go#gobuild#Handler', \ 'lint_file': 1, \}) diff --git a/ale_linters/go/golangci_lint.vim b/ale_linters/go/golangci_lint.vim new file mode 100644 index 00000000..dd9a3c64 --- /dev/null +++ b/ale_linters/go/golangci_lint.vim @@ -0,0 +1,56 @@ +" 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) + \ . '%e run ' + \ . l:options + endif + + return ale#path#BufferCdString(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_callback': ale#VarFunc('go_golangci_lint_executable'), +\ 'command_callback': 'ale_linters#go#golangci_lint#GetCommand', +\ 'callback': 'ale_linters#go#golangci_lint#Handler', +\ 'lint_file': 1, +\}) diff --git a/ale_linters/go/golint.vim b/ale_linters/go/golint.vim index d580fda2..4bf14fcc 100644 --- a/ale_linters/go/golint.vim +++ b/ale_linters/go/golint.vim @@ -1,10 +1,21 @@ " Author: neersighted <bjorn@neersighted.com> " 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 '%e' + \ . (!empty(l:options) ? ' ' . l:options : '') + \ . ' %t' +endfunction + call ale#linter#Define('go', { \ 'name': 'golint', \ 'output_stream': 'both', -\ 'executable': 'golint', -\ 'command': 'golint %t', +\ 'executable_callback': ale#VarFunc('go_golint_executable'), +\ 'command_callback': 'ale_linters#go#golint#GetCommand', \ 'callback': 'ale#handlers#unix#HandleAsWarning', \}) diff --git a/ale_linters/go/gometalinter.vim b/ale_linters/go/gometalinter.vim index 375a8b0f..d005e1d2 100644 --- a/ale_linters/go/gometalinter.vim +++ b/ale_linters/go/gometalinter.vim @@ -5,12 +5,7 @@ call ale#Set('go_gometalinter_options', '') call ale#Set('go_gometalinter_executable', 'gometalinter') 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 - let l:executable = ale_linters#go#gometalinter#GetExecutable(a:buffer) let l:filename = expand('#' . a:buffer . ':t') let l:options = ale#Var(a:buffer, 'go_gometalinter_options') let l:lint_package = ale#Var(a:buffer, 'go_gometalinter_lint_package') @@ -19,12 +14,12 @@ function! ale_linters#go#gometalinter#GetCommand(buffer) abort " be calculated to absolute paths in the Handler if l:lint_package return ale#path#BufferCdString(a:buffer) - \ . ale#Escape(l:executable) + \ . '%e' \ . (!empty(l:options) ? ' ' . l:options : '') . ' .' endif return ale#path#BufferCdString(a:buffer) - \ . ale#Escape(l:executable) + \ . '%e' \ . ' --include=' . ale#Escape(ale#util#EscapePCRE(l:filename)) \ . (!empty(l:options) ? ' ' . l:options : '') . ' .' endfunction @@ -55,7 +50,7 @@ endfunction call ale#linter#Define('go', { \ 'name': 'gometalinter', -\ 'executable_callback': 'ale_linters#go#gometalinter#GetExecutable', +\ 'executable_callback': ale#VarFunc('go_gometalinter_executable'), \ 'command_callback': 'ale_linters#go#gometalinter#GetCommand', \ 'callback': 'ale_linters#go#gometalinter#Handler', \ 'lint_file': 1, diff --git a/ale_linters/go/govet.vim b/ale_linters/go/govet.vim index e94e6ecd..3d0d2adf 100644 --- a/ale_linters/go/govet.vim +++ b/ale_linters/go/govet.vim @@ -4,15 +4,23 @@ " Author: John Eikenberry <jae@zhar.net> " Description: updated to work with go1.10 +call ale#Set('go_go_executable', 'go') +call ale#Set('go_govet_options', '') + function! ale_linters#go#govet#GetCommand(buffer) abort - return ale#path#BufferCdString(a:buffer) . ' go vet .' + let l:options = ale#Var(a:buffer, 'go_govet_options') + + return ale#path#BufferCdString(a:buffer) . ' ' + \ . ale#Var(a:buffer, 'go_go_executable') . ' vet ' + \ . (!empty(l:options) ? ' ' . l:options : '') + \ . ' .' endfunction call ale#linter#Define('go', { \ 'name': 'govet', \ 'aliases': ['go vet'], \ 'output_stream': 'stderr', -\ 'executable': 'go', +\ 'executable_callback': ale#VarFunc('go_go_executable'), \ 'command_callback': 'ale_linters#go#govet#GetCommand', \ 'callback': 'ale#handlers#go#Handler', \ 'lint_file': 1, diff --git a/ale_linters/go/langserver.vim b/ale_linters/go/langserver.vim new file mode 100644 index 00000000..df956483 --- /dev/null +++ b/ale_linters/go/langserver.vim @@ -0,0 +1,28 @@ +" Author: Horacio Sanson <https://github.com/hsanson> +" Description: Support for go-langserver https://github.com/sourcegraph/go-langserver + +call ale#Set('go_langserver_executable', 'go-langserver') +call ale#Set('go_langserver_options', '') + +function! ale_linters#go#langserver#GetCommand(buffer) abort + let l:executable = [ale#Escape(ale#Var(a:buffer, 'go_langserver_executable'))] + let l:options = ale#Var(a:buffer, 'go_langserver_options') + let l:options = substitute(l:options, '-gocodecompletion', '', 'g') + let l:options = filter(split(l:options, ' '), 'empty(v:val) != 1') + + if(ale#Var(a:buffer, 'completion_enabled') == 1) + call add(l:options, '-gocodecompletion') + endif + + let l:options = uniq(sort(l:options)) + + return join(extend(l:executable, l:options), ' ') +endfunction + +call ale#linter#Define('go', { +\ 'name': 'golangserver', +\ 'lsp': 'stdio', +\ 'executable_callback': ale#VarFunc('go_langserver_executable'), +\ 'command_callback': 'ale_linters#go#langserver#GetCommand', +\ 'project_root_callback': 'ale#go#FindProjectRoot', +\}) diff --git a/ale_linters/hack/hack.vim b/ale_linters/hack/hack.vim new file mode 100644 index 00000000..aea428cc --- /dev/null +++ b/ale_linters/hack/hack.vim @@ -0,0 +1,22 @@ +" Author: Fred Emmott <fe@fb.com> +" Description: Hack support via `hack lsp` + +call ale#Set('hack_hack_executable', 'hh_client') + +function! ale_linters#hack#hack#GetProjectRoot(buffer) abort + let l:hhconfig = ale#path#FindNearestFile(a:buffer, '.hhconfig') + + return !empty(l:hhconfig) ? fnamemodify(l:hhconfig, ':h') : '' +endfunction + +function! ale_linters#hack#hack#GetExecutable(buffer) abort + return ale#Var(a:buffer, 'hack_hack_executable') +endfunction + +call ale#linter#Define('hack', { +\ 'name': 'hack', +\ 'lsp': 'stdio', +\ 'executable_callback': 'ale_linters#hack#hack#GetExecutable', +\ 'command': '%e lsp --from vim-ale', +\ 'project_root_callback': 'ale_linters#hack#hack#GetProjectRoot', +\}) diff --git a/ale_linters/hack/hhast.vim b/ale_linters/hack/hhast.vim new file mode 100644 index 00000000..710b7b25 --- /dev/null +++ b/ale_linters/hack/hhast.vim @@ -0,0 +1,40 @@ +" Author: Fred Emmott <fe@fb.com> +" Description: Hack support via `hhast lsp` + +call ale#Set('hack_hhast_executable', 'vendor/bin/hhast-lint') + +function! ale_linters#hack#hhast#GetProjectRoot(buffer) abort + " Find the hack root, then figure out if it's also an HHAST root. + " Don't try to use lint configurations from vendor/foo/bar/hhast-lint.json + let l:hhconfig = ale#path#FindNearestFile(a:buffer, '.hhconfig') + + if empty(l:hhconfig) + return '' + endif + + let l:root = fnamemodify(l:hhconfig, ':h') + let l:hhast_config = findfile('hhast-lint.json', l:root) + + return !empty(l:hhast_config) ? l:root : '' +endfunction + +function! ale_linters#hack#hhast#GetExecutable(buffer) abort + let l:root = ale_linters#hack#hhast#GetProjectRoot(a:buffer) + let l:relative = ale#Var(a:buffer, 'hack_hhast_executable') + let l:absolute = findfile(l:relative, l:root) + + return !empty(l:absolute) ? l:absolute : '' +endfunction + +function! ale_linters#hack#hhast#GetInitializationOptions(buffer) abort + return {'lintMode': 'open-files'} +endfunction + +call ale#linter#Define('hack', { +\ 'name': 'hhast', +\ 'lsp': 'stdio', +\ 'executable_callback': 'ale_linters#hack#hhast#GetExecutable', +\ 'command': '%e --mode lsp --from vim-ale', +\ 'project_root_callback': 'ale_linters#hack#hhast#GetProjectRoot', +\ 'initialization_options_callback': 'ale_linters#hack#hhast#GetInitializationOptions', +\}) diff --git a/ale_linters/haml/hamllint.vim b/ale_linters/haml/hamllint.vim index d6633599..6598f81a 100644 --- a/ale_linters/haml/hamllint.vim +++ b/ale_linters/haml/hamllint.vim @@ -1,6 +1,12 @@ " Author: Patrick Lewis - https://github.com/patricklewis, thenoseman - https://github.com/thenoseman " Description: haml-lint for Haml files +call ale#Set('haml_hamllint_executable', 'haml-lint') + +function! ale_linters#haml#hamllint#GetExecutable(buffer) abort + return ale#Var(a:buffer, 'haml_hamllint_executable') +endfunction + function! ale_linters#haml#hamllint#GetCommand(buffer) abort let l:prefix = '' @@ -21,7 +27,7 @@ function! ale_linters#haml#hamllint#GetCommand(buffer) abort endif return (!empty(l:prefix) ? l:prefix . ' ' : '') - \ . 'haml-lint' + \ . ale_linters#haml#hamllint#GetExecutable(a:buffer) \ . (!empty(l:hamllint_config_file_path) ? ' --config ' . ale#Escape(l:hamllint_config_file_path) : '') \ . ' %t' endfunction @@ -45,7 +51,7 @@ endfunction call ale#linter#Define('haml', { \ 'name': 'hamllint', -\ 'executable': 'haml-lint', +\ 'executable_callback': 'ale_linters#haml#hamllint#GetExecutable', \ 'command_callback': 'ale_linters#haml#hamllint#GetCommand', \ 'callback': 'ale_linters#haml#hamllint#Handle' \}) diff --git a/ale_linters/handlebars/embertemplatelint.vim b/ale_linters/handlebars/embertemplatelint.vim index 162a033c..4fc0f20d 100644 --- a/ale_linters/handlebars/embertemplatelint.vim +++ b/ale_linters/handlebars/embertemplatelint.vim @@ -4,17 +4,6 @@ call ale#Set('handlebars_embertemplatelint_executable', 'ember-template-lint') call ale#Set('handlebars_embertemplatelint_use_global', get(g:, 'ale_use_global_executables', 0)) -function! ale_linters#handlebars#embertemplatelint#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'handlebars_embertemplatelint', [ - \ 'node_modules/.bin/ember-template-lint', - \]) -endfunction - -function! ale_linters#handlebars#embertemplatelint#GetCommand(buffer) abort - return ale_linters#handlebars#embertemplatelint#GetExecutable(a:buffer) - \ . ' --json %t' -endfunction - function! ale_linters#handlebars#embertemplatelint#Handle(buffer, lines) abort let l:output = [] let l:json = ale#util#FuzzyJSONDecode(a:lines, {}) @@ -42,7 +31,9 @@ endfunction call ale#linter#Define('handlebars', { \ 'name': 'ember-template-lint', -\ 'executable_callback': 'ale_linters#handlebars#embertemplatelint#GetExecutable', -\ 'command_callback': 'ale_linters#handlebars#embertemplatelint#GetCommand', +\ 'executable_callback': ale#node#FindExecutableFunc('handlebars_embertemplatelint', [ +\ 'node_modules/.bin/ember-template-lint', +\ ]), +\ 'command': '%e --json %t', \ 'callback': 'ale_linters#handlebars#embertemplatelint#Handle', \}) diff --git a/ale_linters/haskell/ghc-mod.vim b/ale_linters/haskell/ghc-mod.vim deleted file mode 100644 index eb032f50..00000000 --- a/ale_linters/haskell/ghc-mod.vim +++ /dev/null @@ -1,18 +0,0 @@ -" Author: wizzup <wizzup@gmail.com> -" Description: ghc-mod for Haskell files - -call ale#linter#Define('haskell', { -\ 'name': 'ghc_mod', -\ 'aliases': ['ghc-mod'], -\ 'executable': 'ghc-mod', -\ 'command': 'ghc-mod --map-file %s=%t check %s', -\ 'callback': 'ale#handlers#haskell#HandleGHCFormat', -\}) - -call ale#linter#Define('haskell', { -\ 'name': 'stack_ghc_mod', -\ 'aliases': ['stack-ghc-mod'], -\ 'executable': 'stack', -\ 'command': 'stack exec ghc-mod -- --map-file %s=%t check %s', -\ 'callback': 'ale#handlers#haskell#HandleGHCFormat', -\}) diff --git a/ale_linters/haskell/ghc_mod.vim b/ale_linters/haskell/ghc_mod.vim new file mode 100644 index 00000000..9762be7a --- /dev/null +++ b/ale_linters/haskell/ghc_mod.vim @@ -0,0 +1,19 @@ +" Author: wizzup <wizzup@gmail.com> +" Description: ghc-mod for Haskell files + +call ale#Set('haskell_ghc_mod_executable', 'ghc-mod') + +function! ale_linters#haskell#ghc_mod#GetCommand (buffer) abort + let l:executable = ale#Var(a:buffer, 'haskell_ghc_mod_executable') + + return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'ghc-mod') + \ . ' --map-file %s=%t check %s' +endfunction + +call ale#linter#Define('haskell', { +\ 'name': 'ghc_mod', +\ 'aliases': ['ghc-mod'], +\ 'executable_callback': ale#VarFunc('haskell_ghc_mod_executable'), +\ 'command_callback': 'ale_linters#haskell#ghc_mod#GetCommand', +\ 'callback': 'ale#handlers#haskell#HandleGHCFormat', +\}) diff --git a/ale_linters/haskell/hdevtools.vim b/ale_linters/haskell/hdevtools.vim index dc902152..cc5ce56f 100644 --- a/ale_linters/haskell/hdevtools.vim +++ b/ale_linters/haskell/hdevtools.vim @@ -4,19 +4,17 @@ call ale#Set('haskell_hdevtools_executable', 'hdevtools') call ale#Set('haskell_hdevtools_options', get(g:, 'hdevtools_options', '-g -Wall')) -function! ale_linters#haskell#hdevtools#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'haskell_hdevtools_executable') -endfunction - function! ale_linters#haskell#hdevtools#GetCommand(buffer) abort - return ale#Escape(ale_linters#haskell#hdevtools#GetExecutable(a:buffer)) - \ . ' check ' . ale#Var(a:buffer, 'haskell_hdevtools_options') - \ . ' -p %s %t' + let l:executable = ale#Var(a:buffer, 'haskell_hdevtools_executable') + + return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'hdevtools') + \ . ' check' . ale#Pad(ale#Var(a:buffer, 'haskell_hdevtools_options')) + \ . ' -p %s %t' endfunction call ale#linter#Define('haskell', { \ 'name': 'hdevtools', -\ 'executable_callback': 'ale_linters#haskell#hdevtools#GetExecutable', +\ 'executable_callback': ale#VarFunc('haskell_hdevtools_executable'), \ 'command_callback': 'ale_linters#haskell#hdevtools#GetCommand', \ 'callback': 'ale#handlers#haskell#HandleGHCFormat', \}) diff --git a/ale_linters/haskell/hie.vim b/ale_linters/haskell/hie.vim new file mode 100644 index 00000000..3ff1180a --- /dev/null +++ b/ale_linters/haskell/hie.vim @@ -0,0 +1,47 @@ +" Author: Luxed <devildead13@gmail.com> +" Description: A language server for Haskell + +call ale#Set('haskell_hie_executable', 'hie') + +function! ale_linters#haskell#hie#GetProjectRoot(buffer) abort + " Search for the stack file first + let l:project_file = ale#path#FindNearestFile(a:buffer, 'stack.yaml') + + " If it's empty, search for the cabal file + if empty(l:project_file) + let l:cabal_file = fnamemodify(bufname(a:buffer), ':p:h') + let l:paths = '' + + while empty(matchstr(l:cabal_file, '^\(\/\|\(\w:\\\)\)$')) + let l:cabal_file = fnamemodify(l:cabal_file, ':h') + let l:paths = l:paths . l:cabal_file . ',' + endwhile + + let l:project_file = globpath(l:paths, '*.cabal') + endif + + " Either extract the project directory or take the current working + " directory + if !empty(l:project_file) + let l:project_file = fnamemodify(l:project_file, ':h') + else + let l:project_file = expand('#' . a:buffer . ':p:h') + endif + + return l:project_file +endfunction + +function! ale_linters#haskell#hie#GetCommand(buffer) abort + let l:executable = ale#Var(a:buffer, 'haskell_hie_executable') + + return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'hie') +\ . ' --lsp' +endfunction + +call ale#linter#Define('haskell', { +\ 'name': 'hie', +\ 'lsp': 'stdio', +\ 'command_callback': 'ale_linters#haskell#hie#GetCommand', +\ 'executable_callback': ale#VarFunc('haskell_hie_executable'), +\ 'project_root_callback': 'ale_linters#haskell#hie#GetProjectRoot', +\}) diff --git a/ale_linters/haskell/hlint.vim b/ale_linters/haskell/hlint.vim index be40d92c..0cc7437f 100644 --- a/ale_linters/haskell/hlint.vim +++ b/ale_linters/haskell/hlint.vim @@ -1,6 +1,9 @@ " Author: jparoz <jesse.paroz@gmail.com> " Description: hlint for Haskell files +call ale#Set('haskell_hlint_executable', 'hlint') +call ale#Set('haskell_hlint_options', get(g:, 'hlint_options', '')) + function! ale_linters#haskell#hlint#Handle(buffer, lines) abort let l:output = [] @@ -26,9 +29,18 @@ function! ale_linters#haskell#hlint#Handle(buffer, lines) abort return l:output endfunction +function! ale_linters#haskell#hlint#GetCommand(buffer) abort + let l:hlintopts = '--color=never --json' + + return ale#handlers#hlint#GetExecutable(a:buffer) + \ . ' ' . ale#Var(a:buffer, 'haskell_hlint_options') + \ . ' ' . l:hlintopts + \ . ' -' +endfunction + call ale#linter#Define('haskell', { \ 'name': 'hlint', -\ 'executable': 'hlint', -\ 'command': 'hlint --color=never --json -', +\ 'executable_callback': ale#VarFunc('haskell_hlint_executable'), +\ 'command_callback': 'ale_linters#haskell#hlint#GetCommand' , \ 'callback': 'ale_linters#haskell#hlint#Handle', \}) diff --git a/ale_linters/haskell/stack_build.vim b/ale_linters/haskell/stack_build.vim index f5bdf4b8..95a54587 100644 --- a/ale_linters/haskell/stack_build.vim +++ b/ale_linters/haskell/stack_build.vim @@ -16,7 +16,7 @@ call ale#linter#Define('haskell', { \ 'name': 'stack_build', \ 'aliases': ['stack-build'], \ 'output_stream': 'stderr', -\ 'executable': 'stack', +\ 'executable_callback': 'ale#handlers#haskell#GetStackExecutable', \ 'command_callback': 'ale_linters#haskell#stack_build#GetCommand', \ 'lint_file': 1, \ 'callback': 'ale#handlers#haskell#HandleGHCFormat', diff --git a/ale_linters/haskell/stack_ghc.vim b/ale_linters/haskell/stack_ghc.vim index d702aa68..8f42b96c 100644 --- a/ale_linters/haskell/stack_ghc.vim +++ b/ale_linters/haskell/stack_ghc.vim @@ -5,7 +5,7 @@ call ale#linter#Define('haskell', { \ 'name': 'stack_ghc', \ 'aliases': ['stack-ghc'], \ 'output_stream': 'stderr', -\ 'executable': 'stack', +\ 'executable_callback': 'ale#handlers#haskell#GetStackExecutable', \ 'command': 'stack ghc -- -fno-code -v0 %t', \ 'callback': 'ale#handlers#haskell#HandleGHCFormat', \}) diff --git a/ale_linters/html/htmlhint.vim b/ale_linters/html/htmlhint.vim index caa15bbb..234c1176 100644 --- a/ale_linters/html/htmlhint.vim +++ b/ale_linters/html/htmlhint.vim @@ -5,12 +5,6 @@ call ale#Set('html_htmlhint_options', '') call ale#Set('html_htmlhint_executable', 'htmlhint') call ale#Set('html_htmlhint_use_global', get(g:, 'ale_use_global_executables', 0)) -function! ale_linters#html#htmlhint#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'html_htmlhint', [ - \ 'node_modules/.bin/htmlhint', - \]) -endfunction - function! ale_linters#html#htmlhint#GetCommand(buffer) abort let l:options = ale#Var(a:buffer, 'html_htmlhint_options') let l:config = l:options !~# '--config' @@ -25,14 +19,14 @@ function! ale_linters#html#htmlhint#GetCommand(buffer) abort let l:options = substitute(l:options, '--format=unix', '', '') endif - return ale#Escape(ale_linters#html#htmlhint#GetExecutable(a:buffer)) - \ . (!empty(l:options) ? ' ' . l:options : '') - \ . ' --format=unix %t' + return '%e' . ale#Pad(l:options) . ' --format=unix %t' endfunction call ale#linter#Define('html', { \ 'name': 'htmlhint', -\ 'executable_callback': 'ale_linters#html#htmlhint#GetExecutable', +\ 'executable_callback': ale#node#FindExecutableFunc('html_htmlhint', [ +\ 'node_modules/.bin/htmlhint', +\ ]), \ 'command_callback': 'ale_linters#html#htmlhint#GetCommand', \ 'callback': 'ale#handlers#unix#HandleAsError', \}) diff --git a/ale_linters/html/stylelint.vim b/ale_linters/html/stylelint.vim new file mode 100644 index 00000000..908c4b02 --- /dev/null +++ b/ale_linters/html/stylelint.vim @@ -0,0 +1,27 @@ +" Author: Filipe Kiss <hello@filipekiss.com.br> http://github.com/filipekiss + +call ale#Set('html_stylelint_executable', 'stylelint') +call ale#Set('html_stylelint_options', '') +call ale#Set('html_stylelint_use_global', 0) + +function! ale_linters#html#stylelint#GetExecutable(buffer) abort + return ale#node#FindExecutable(a:buffer, 'html_stylelint', [ + \ 'node_modules/.bin/stylelint', + \]) +endfunction + +function! ale_linters#html#stylelint#GetCommand(buffer) abort + let l:executable = ale_linters#html#stylelint#GetExecutable(a:buffer) + let l:options = ale#Var(a:buffer, 'html_stylelint_options') + + return ale#Escape(l:executable) + \ . (!empty(l:options) ? ' ' . l:options : '') + \ . ' --stdin-filename %s' +endfunction + +call ale#linter#Define('html', { +\ 'name': 'stylelint', +\ 'executable_callback': 'ale_linters#html#stylelint#GetExecutable', +\ 'command_callback': 'ale_linters#html#stylelint#GetCommand', +\ 'callback': 'ale#handlers#css#HandleStyleLintFormat', +\}) diff --git a/ale_linters/html/tidy.vim b/ale_linters/html/tidy.vim index 913cdade..4ec29091 100644 --- a/ale_linters/html/tidy.vim +++ b/ale_linters/html/tidy.vim @@ -25,6 +25,7 @@ function! ale_linters#html#tidy#GetCommand(buffer) abort " On macOS, old tidy (released on 31 Oct 2006) is installed. It does not " consider HTML5 so we should avoid it. let l:executable = ale#Var(a:buffer, 'html_tidy_executable') + if has('mac') && l:executable is# 'tidy' && exists('*exepath') \ && exepath(l:executable) is# '/usr/bin/tidy' return '' @@ -37,14 +38,9 @@ function! ale_linters#html#tidy#GetCommand(buffer) abort \) endfunction -function! ale_linters#html#tidy#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'html_tidy_executable') -endfunction - function! ale_linters#html#tidy#Handle(buffer, lines) abort " Matches patterns lines like the following: " line 7 column 5 - Warning: missing </title> before </head> - let l:pattern = '^line \(\d\+\) column \(\d\+\) - \(Warning\|Error\): \(.\+\)$' let l:output = [] @@ -67,7 +63,7 @@ endfunction call ale#linter#Define('html', { \ 'name': 'tidy', -\ 'executable_callback': 'ale_linters#html#tidy#GetExecutable', +\ 'executable_callback': ale#VarFunc('html_tidy_executable'), \ 'output_stream': 'stderr', \ 'command_callback': 'ale_linters#html#tidy#GetCommand', \ 'callback': 'ale_linters#html#tidy#Handle', diff --git a/ale_linters/idris/idris.vim b/ale_linters/idris/idris.vim index 115d04fc..feac0f10 100644 --- a/ale_linters/idris/idris.vim +++ b/ale_linters/idris/idris.vim @@ -4,21 +4,15 @@ call ale#Set('idris_idris_executable', 'idris') call ale#Set('idris_idris_options', '--total --warnpartial --warnreach --warnipkg') -function! ale_linters#idris#idris#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'idris_idris_executable') -endfunction - function! ale_linters#idris#idris#GetCommand(buffer) abort let l:options = ale#Var(a:buffer, 'idris_idris_options') - return ale#Escape(ale_linters#idris#idris#GetExecutable(a:buffer)) - \ . (!empty(l:options) ? ' ' . l:options : '') - \ . ' --check %s' + return '%e' . ale#Pad(l:options) . ' --check %s' endfunction function! ale_linters#idris#idris#Handle(buffer, lines) abort " This was copied almost verbatim from ale#handlers#haskell#HandleGHCFormat - + " " Look for lines like the following: " foo.idr:2:6:When checking right hand side of main with expected type " bar.idr:11:11-13: @@ -36,6 +30,7 @@ function! ale_linters#idris#idris#Handle(buffer, lines) abort else let l:corrected_lines[-1] .= l:line endif + let l:corrected_lines[-1] = substitute(l:corrected_lines[-1], '\s\+', ' ', 'g') endif endfor @@ -80,8 +75,7 @@ endfunction call ale#linter#Define('idris', { \ 'name': 'idris', -\ 'executable_callback': 'ale_linters#idris#idris#GetExecutable', +\ 'executable_callback': ale#VarFunc('idris_idris_executable'), \ 'command_callback': 'ale_linters#idris#idris#GetCommand', \ 'callback': 'ale_linters#idris#idris#Handle', \}) - diff --git a/ale_linters/ispc/ispc.vim b/ale_linters/ispc/ispc.vim new file mode 100644 index 00000000..de7ceafa --- /dev/null +++ b/ale_linters/ispc/ispc.vim @@ -0,0 +1,45 @@ +" Author: Martino Pilia <martino.pilia@gmail.com> +" Description: Lint ispc files with the Intel(R) SPMD Program Compiler + +call ale#Set('ispc_ispc_executable', 'ispc') +call ale#Set('ispc_ispc_options', '') + +function! ale_linters#ispc#ispc#GetCommand(buffer) abort + " --nowrap: do not wrap message lines + return '%e --nowrap' + \ . ale#Pad(ale#c#IncludeOptions(ale#c#FindLocalHeaderPaths(a:buffer))) + \ . ale#Pad(ale#Var(a:buffer, 'ispc_ispc_options')) + \ . ' %s' +endfunction + +" Note that we ignore the two warnings in the beginning of the compiler output +" ('no output file specified' and 'no --target specified'), since they have +" nothing to do with linting. +function! ale_linters#ispc#ispc#Handle(buffer, lines) abort + " Message format: <filename>:<lnum>:<col> <type>: <text> + " As far as I know, <type> can be any of: + " 'error', 'Error', 'fatal error', 'Warning', 'Performance Warning' + let l:re = '\v.+:([0-9]+):([0-9]+):\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[1]), + \ 'col': str2nr(l:match[2]), + \ 'type': l:match[3] =~? 'error' ? 'E' : 'W', + \ 'text': l:match[4], + \}) + endfor + + return l:output +endfunction + +call ale#linter#Define('ispc', { +\ 'name': 'ispc', +\ 'output_stream': 'stderr', +\ 'executable_callback': ale#VarFunc('ispc_ispc_executable'), +\ 'command_callback': 'ale_linters#ispc#ispc#GetCommand', +\ 'callback': 'ale_linters#ispc#ispc#Handle', +\ 'lint_file': 1, +\}) diff --git a/ale_linters/java/checkstyle.vim b/ale_linters/java/checkstyle.vim index 8155170a..c07b65d0 100644 --- a/ale_linters/java/checkstyle.vim +++ b/ale_linters/java/checkstyle.vim @@ -2,9 +2,11 @@ " Description: checkstyle for Java files function! ale_linters#java#checkstyle#Handle(buffer, lines) abort - let l:pattern = '\v\[(WARN|ERROR)\] [a-zA-Z]?:?[^:]+:(\d+):(\d+)?:? (.*) \[(.+)\]$' let l:output = [] + " modern checkstyle versions + 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, { \ 'type': l:match[1] is? 'WARN' ? 'W' : 'E', @@ -15,13 +17,24 @@ function! ale_linters#java#checkstyle#Handle(buffer, lines) abort \}) endfor + " old checkstyle versions + let l:pattern = '\v(.+):(\d+): ([^:]+): (.+)$' + + for l:match in ale#util#GetMatches(a:lines, l:pattern) + call add(l:output, { + \ 'type': l:match[3] is? 'warning' ? 'W' : 'E', + \ 'lnum': l:match[2] + 0, + \ 'text': l:match[4], + \}) + endfor + return l:output endfunction function! ale_linters#java#checkstyle#GetCommand(buffer) abort return 'checkstyle ' \ . ale#Var(a:buffer, 'java_checkstyle_options') - \ . ' %t' + \ . ' %s' endfunction if !exists('g:ale_java_checkstyle_options') @@ -33,4 +46,5 @@ call ale#linter#Define('java', { \ 'executable': 'checkstyle', \ 'command_callback': 'ale_linters#java#checkstyle#GetCommand', \ 'callback': 'ale_linters#java#checkstyle#Handle', +\ 'lint_file': 1, \}) diff --git a/ale_linters/java/javac.vim b/ale_linters/java/javac.vim index d7a39aa7..63dcdd94 100644 --- a/ale_linters/java/javac.vim +++ b/ale_linters/java/javac.vim @@ -16,6 +16,7 @@ function! ale_linters#java#javac#GetImportPaths(buffer) abort endif let l:classpath_command = ale#gradle#BuildClasspathCommand(a:buffer) + if !empty(l:classpath_command) return l:classpath_command endif @@ -36,10 +37,6 @@ function! s:BuildClassPathOption(buffer, import_paths) abort \ : '' endfunction -function! ale_linters#java#javac#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'java_javac_executable') -endfunction - function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort let l:cp_option = s:BuildClassPathOption(a:buffer, a:import_paths) let l:sp_option = '' @@ -77,13 +74,11 @@ function! ale_linters#java#javac#GetCommand(buffer, import_paths) abort " Create .class files in a temporary directory, which we will delete later. let l:class_file_directory = ale#engine#CreateDirectory(a:buffer) - let l:executable = ale_linters#java#javac#GetExecutable(a:buffer) " Always run javac from the directory the file is in, so we can resolve " relative paths correctly. return ale#path#BufferCdString(a:buffer) - \ . ale#Escape(l:executable) - \ . ' -Xlint' + \ . '%e -Xlint' \ . ale#Pad(l:cp_option) \ . ale#Pad(l:sp_option) \ . ' -d ' . ale#Escape(l:class_file_directory) @@ -96,7 +91,6 @@ function! ale_linters#java#javac#Handle(buffer, lines) abort " " Main.java:13: warning: [deprecation] donaught() in Testclass has been deprecated " Main.java:16: error: ';' expected - let l:directory = expand('#' . a:buffer . ':p:h') let l:pattern = '\v^(.*):(\d+): (.+):(.+)$' let l:col_pattern = '\v^(\s*\^)$' @@ -126,7 +120,7 @@ endfunction call ale#linter#Define('java', { \ 'name': 'javac', -\ 'executable_callback': 'ale_linters#java#javac#GetExecutable', +\ 'executable_callback': ale#VarFunc('java_javac_executable'), \ 'command_chain': [ \ {'callback': 'ale_linters#java#javac#GetImportPaths', 'output_stream': 'stdout'}, \ {'callback': 'ale_linters#java#javac#GetCommand', 'output_stream': 'stderr'}, diff --git a/ale_linters/java/javalsp.vim b/ale_linters/java/javalsp.vim new file mode 100644 index 00000000..5d1a0c63 --- /dev/null +++ b/ale_linters/java/javalsp.vim @@ -0,0 +1,23 @@ +" Author: Horacio Sanson <https://github.com/hsanson> +" Description: Support for the Java language server https://github.com/georgewfraser/vscode-javac + +call ale#Set('java_javalsp_jar', 'javacs.jar') + +function! ale_linters#java#javalsp#Executable(buffer) abort + return 'java' +endfunction + +function! ale_linters#java#javalsp#Command(buffer) abort + let l:jar = ale#Var(a:buffer, 'java_javalsp_jar') + + return ale#Escape('java -cp ' . l:jar . ' -Xverify:none org.javacs.Main') +endfunction + +call ale#linter#Define('java', { +\ 'name': 'javalsp', +\ 'lsp': 'stdio', +\ 'executable_callback': 'ale_linters#java#javalsp#Executable', +\ 'command_callback': 'ale_linters#java#javalsp#Command', +\ 'language': 'java', +\ 'project_root_callback': 'ale#java#FindProjectRoot', +\}) diff --git a/ale_linters/java/pmd.vim b/ale_linters/java/pmd.vim index d461e094..b530ad09 100644 --- a/ale_linters/java/pmd.vim +++ b/ale_linters/java/pmd.vim @@ -2,7 +2,7 @@ " Description: PMD for Java files function! ale_linters#java#pmd#Handle(buffer, lines) abort - let l:pattern = '"\(\d\+\)",".\+","\(.\+\)","\(\d\+\)","\(\d\+\)","\(.\+\)","\(.\+\)","\(.\+\)"$' + let l:pattern = '"\(\d\+\)",".*","\(.\+\)","\(\d\+\)","\(\d\+\)","\(.\+\)","\(.\+\)","\(.\+\)"$' let l:output = [] for l:match in ale#util#GetMatches(a:lines, l:pattern) diff --git a/ale_linters/javascript/flow.vim b/ale_linters/javascript/flow.vim index d555184e..cdb289c7 100755 --- a/ale_linters/javascript/flow.vim +++ b/ale_linters/javascript/flow.vim @@ -91,7 +91,6 @@ function! s:GetDetails(error) abort let l:detail = '' for l:extra_error in a:error.extra - if has_key(l:extra_error, 'message') for l:extra_message in l:extra_error.message let l:detail = s:ExtraErrorMsg(l:detail, l:extra_message.descr) @@ -105,7 +104,6 @@ function! s:GetDetails(error) abort endfor endfor endif - endfor return l:detail @@ -161,7 +159,6 @@ function! ale_linters#javascript#flow#Handle(buffer, lines) abort endif call add(l:output, l:errorToAdd) - endfor return l:output diff --git a/ale_linters/javascript/flow_ls.vim b/ale_linters/javascript/flow_ls.vim index 20fc2217..75377183 100644 --- a/ale_linters/javascript/flow_ls.vim +++ b/ale_linters/javascript/flow_ls.vim @@ -6,18 +6,6 @@ call ale#Set('javascript_flow_ls_use_global', \ get(g:, 'ale_use_global_executables', 0) \) -function! ale_linters#javascript#flow_ls#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'javascript_flow_ls', [ - \ 'node_modules/.bin/flow', - \]) -endfunction - -function! ale_linters#javascript#flow_ls#GetCommand(buffer) abort - let l:executable = ale_linters#javascript#flow_ls#GetExecutable(a:buffer) - - return ale#Escape(l:executable) . ' lsp --from ale-lsp' -endfunction - function! ale_linters#javascript#flow_ls#FindProjectRoot(buffer) abort let l:flow_config = ale#path#FindNearestFile(a:buffer, '.flowconfig') @@ -31,8 +19,10 @@ endfunction call ale#linter#Define('javascript', { \ 'name': 'flow-language-server', \ 'lsp': 'stdio', -\ 'executable_callback': 'ale_linters#javascript#flow_ls#GetExecutable', -\ 'command_callback': 'ale_linters#javascript#flow_ls#GetCommand', +\ 'executable_callback': ale#node#FindExecutableFunc('javascript_flow_ls', [ +\ 'node_modules/.bin/flow', +\ ]), +\ 'command': '%e lsp --from ale-lsp', \ 'project_root_callback': 'ale_linters#javascript#flow_ls#FindProjectRoot', \ 'language': 'javascript', \}) diff --git a/ale_linters/javascript/jscs.vim b/ale_linters/javascript/jscs.vim index 60044037..a38766a6 100644 --- a/ale_linters/javascript/jscs.vim +++ b/ale_linters/javascript/jscs.vim @@ -4,12 +4,6 @@ call ale#Set('javascript_jscs_executable', 'jscs') call ale#Set('javascript_jscs_use_global', get(g:, 'ale_use_global_executables', 0)) -function! ale_linters#javascript#jscs#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'javascript_jscs', [ - \ 'node_modules/.bin/jscs', - \]) -endfunction - function! ale_linters#javascript#jscs#GetCommand(buffer) abort " Search for a local JShint config locaation, and default to a global one. let l:jscs_config = ale#path#ResolveLocalPath( @@ -18,8 +12,7 @@ function! ale_linters#javascript#jscs#GetCommand(buffer) abort \ get(g:, 'ale_jscs_config_loc', '') \) - let l:command = ale#Escape(ale_linters#javascript#jscs#GetExecutable(a:buffer)) - let l:command .= ' --reporter inline --no-colors' + let l:command = '%e --reporter inline --no-colors' if !empty(l:jscs_config) let l:command .= ' --config ' . ale#Escape(l:jscs_config) @@ -60,8 +53,9 @@ endfunction call ale#linter#Define('javascript', { \ 'name': 'jscs', -\ 'executable_callback': 'ale_linters#javascript#jscs#GetExecutable', +\ 'executable_callback': ale#node#FindExecutableFunc('javascript_jscs', [ +\ 'node_modules/.bin/jscs', +\ ]), \ 'command_callback': 'ale_linters#javascript#jscs#GetCommand', \ 'callback': 'ale_linters#javascript#jscs#Handle', \}) - diff --git a/ale_linters/javascript/jshint.vim b/ale_linters/javascript/jshint.vim index 2e9bb9fd..cb7f66fc 100644 --- a/ale_linters/javascript/jshint.vim +++ b/ale_linters/javascript/jshint.vim @@ -4,12 +4,6 @@ call ale#Set('javascript_jshint_executable', 'jshint') call ale#Set('javascript_jshint_use_global', get(g:, 'ale_use_global_executables', 0)) -function! ale_linters#javascript#jshint#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'javascript_jshint', [ - \ 'node_modules/.bin/jshint', - \]) -endfunction - function! ale_linters#javascript#jshint#GetCommand(buffer) abort " Search for a local JShint config locaation, and default to a global one. let l:jshint_config = ale#path#ResolveLocalPath( @@ -18,21 +12,22 @@ function! ale_linters#javascript#jshint#GetCommand(buffer) abort \ get(g:, 'ale_jshint_config_loc', '') \) - let l:command = ale#Escape(ale_linters#javascript#jshint#GetExecutable(a:buffer)) - let l:command .= ' --reporter unix --extract auto' + let l:command = '%e --reporter unix --extract auto' if !empty(l:jshint_config) let l:command .= ' --config ' . ale#Escape(l:jshint_config) endif - let l:command .= ' -' + let l:command .= ' --filename %s -' return l:command endfunction call ale#linter#Define('javascript', { \ 'name': 'jshint', -\ 'executable_callback': 'ale_linters#javascript#jshint#GetExecutable', +\ 'executable_callback': ale#node#FindExecutableFunc('javascript_jshint', [ +\ 'node_modules/.bin/jshint', +\ ]), \ 'command_callback': 'ale_linters#javascript#jshint#GetCommand', \ 'callback': 'ale#handlers#unix#HandleAsError', \}) diff --git a/ale_linters/javascript/tsserver.vim b/ale_linters/javascript/tsserver.vim index 62dded10..6cf08dd6 100644 --- a/ale_linters/javascript/tsserver.vim +++ b/ale_linters/javascript/tsserver.vim @@ -5,22 +5,13 @@ call ale#Set('javascript_tsserver_executable', 'tsserver') call ale#Set('javascript_tsserver_config_path', '') call ale#Set('javascript_tsserver_use_global', get(g:, 'ale_use_global_executables', 0)) -" These functions need to be defined just to comply with the API for LSP. -function! ale_linters#javascript#tsserver#GetProjectRoot(buffer) abort - return '' -endfunction - -function! ale_linters#javascript#tsserver#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'javascript_tsserver', [ - \ 'node_modules/.bin/tsserver', - \]) -endfunction - call ale#linter#Define('javascript', { \ 'name': 'tsserver', \ 'lsp': 'tsserver', -\ 'executable_callback': 'ale_linters#javascript#tsserver#GetExecutable', -\ 'command_callback': 'ale_linters#javascript#tsserver#GetExecutable', -\ 'project_root_callback': 'ale_linters#javascript#tsserver#GetProjectRoot', +\ 'executable_callback': ale#node#FindExecutableFunc('javascript_tsserver', [ +\ 'node_modules/.bin/tsserver', +\ ]), +\ 'command': '%e', +\ 'project_root_callback': {-> ''}, \ 'language': '', \}) diff --git a/ale_linters/json/jsonlint.vim b/ale_linters/json/jsonlint.vim index 75f47088..f01553d6 100644 --- a/ale_linters/json/jsonlint.vim +++ b/ale_linters/json/jsonlint.vim @@ -3,7 +3,6 @@ function! ale_linters#json#jsonlint#Handle(buffer, lines) abort " Matches patterns like the following: " line 2, col 15, found: 'STRING' - expected: 'EOF', '}', ',', ']'. - let l:pattern = '^line \(\d\+\), col \(\d*\), \(.\+\)$' let l:output = [] diff --git a/ale_linters/julia/languageserver.vim b/ale_linters/julia/languageserver.vim new file mode 100644 index 00000000..cd2000de --- /dev/null +++ b/ale_linters/julia/languageserver.vim @@ -0,0 +1,21 @@ +" Author: Bartolomeo Stellato <bartolomeo.stellato@gmail.com> +" Description: A language server for Julia + +" Set julia executable variable +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);' + + return ale#Escape(l:julia_executable) . ' --startup-file=no --history-file=no -e ' . ale#Escape(l:cmd_string) +endfunction + +call ale#linter#Define('julia', { +\ 'name': 'languageserver', +\ 'lsp': 'stdio', +\ 'executable_callback': ale#VarFunc('julia_executable'), +\ 'command_callback': 'ale_linters#julia#languageserver#GetCommand', +\ 'language': 'julia', +\ 'project_root_callback': 'ale#julia#FindProjectRoot', +\}) diff --git a/ale_linters/kotlin/kotlinc.vim b/ale_linters/kotlin/kotlinc.vim index 00f94be5..4a993986 100644 --- a/ale_linters/kotlin/kotlinc.vim +++ b/ale_linters/kotlin/kotlinc.vim @@ -17,12 +17,14 @@ function! ale_linters#kotlin#kotlinc#GetImportPaths(buffer) abort return '' else let l:pom_path = ale#path#FindNearestFile(a:buffer, 'pom.xml') + if !empty(l:pom_path) && executable('mvn') return ale#path#CdString(fnamemodify(l:pom_path, ':h')) \ . 'mvn dependency:build-classpath' endif let l:classpath_command = ale#gradle#BuildClasspathCommand(a:buffer) + if !empty(l:classpath_command) return l:classpath_command endif @@ -78,12 +80,13 @@ function! ale_linters#kotlin#kotlinc#GetCommand(buffer, import_paths) abort endif let l:fname = '' + if ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath') isnot# '' let l:fname .= expand(ale#Var(a:buffer, 'kotlin_kotlinc_sourcepath'), 1) . ' ' else " Find the src directory for files in this project. - let l:project_root = ale#gradle#FindProjectRoot(a:buffer) + if !empty(l:project_root) let l:src_dir = l:project_root else @@ -93,6 +96,7 @@ function! ale_linters#kotlin#kotlinc#GetCommand(buffer, import_paths) abort let l:fname .= expand(l:src_dir, 1) . ' ' endif + let l:fname .= ale#Escape(expand('#' . a:buffer . ':p')) let l:command .= l:kotlinc_opts . ' ' . l:fname @@ -124,6 +128,7 @@ function! ale_linters#kotlin#kotlinc#Handle(buffer, lines) abort if l:buf_abspath isnot# l:curbuf_abspath continue endif + let l:type_marker_str = l:type is# 'warning' ? 'W' : 'E' call add(l:output, { diff --git a/ale_linters/kotlin/languageserver.vim b/ale_linters/kotlin/languageserver.vim index 0ab673ec..aea817ba 100644 --- a/ale_linters/kotlin/languageserver.vim +++ b/ale_linters/kotlin/languageserver.vim @@ -3,15 +3,6 @@ call ale#Set('kotlin_languageserver_executable', 'kotlin-language-server') -function! ale_linters#kotlin#languageserver#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'kotlin_languageserver_executable') -endfunction - -function! ale_linters#kotlin#languageserver#GetCommand(buffer) abort - let l:executable = ale_linters#kotlin#languageserver#GetExecutable(a:buffer) - return ale#Escape(l:executable) -endfunction - function! ale_linters#kotlin#languageserver#GetProjectRoot(buffer) abort let l:gradle_root = ale#gradle#FindProjectRoot(a:buffer) @@ -31,8 +22,8 @@ endfunction call ale#linter#Define('kotlin', { \ 'name': 'languageserver', \ 'lsp': 'stdio', -\ 'executable_callback': 'ale_linters#kotlin#languageserver#GetExecutable', -\ 'command_callback': 'ale_linters#kotlin#languageserver#GetCommand', +\ 'executable_callback': ale#VarFunc('kotlin_languageserver_executable'), +\ 'command': '%e', \ 'language': 'kotlin', \ 'project_root_callback': 'ale_linters#kotlin#languageserver#GetProjectRoot', \}) diff --git a/ale_linters/less/lessc.vim b/ale_linters/less/lessc.vim index 5fd9a383..37600649 100755 --- a/ale_linters/less/lessc.vim +++ b/ale_linters/less/lessc.vim @@ -5,21 +5,10 @@ call ale#Set('less_lessc_executable', 'lessc') call ale#Set('less_lessc_options', '') call ale#Set('less_lessc_use_global', get(g:, 'ale_use_global_executables', 0)) -function! ale_linters#less#lessc#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'less_lessc', [ - \ 'node_modules/.bin/lessc', - \]) -endfunction - function! ale_linters#less#lessc#GetCommand(buffer) abort - let l:executable = ale_linters#less#lessc#GetExecutable(a:buffer) - let l:dir = expand('#' . a:buffer . ':p:h') - let l:options = ale#Var(a:buffer, 'less_lessc_options') - - return ale#Escape(l:executable) - \ . ' --no-color --lint' - \ . ' --include-path=' . ale#Escape(l:dir) - \ . (!empty(l:options) ? ' ' . l:options : '') + return '%e --no-color --lint' + \ . ' --include-path=' . ale#Escape(expand('#' . a:buffer . ':p:h')) + \ . ale#Pad(ale#Var(a:buffer, 'less_lessc_options')) \ . ' -' endfunction @@ -49,7 +38,9 @@ endfunction call ale#linter#Define('less', { \ 'name': 'lessc', -\ 'executable_callback': 'ale_linters#less#lessc#GetExecutable', +\ 'executable_callback': ale#node#FindExecutableFunc('less_lessc', [ +\ 'node_modules/.bin/lessc', +\ ]), \ 'command_callback': 'ale_linters#less#lessc#GetCommand', \ 'callback': 'ale_linters#less#lessc#Handle', \ 'output_stream': 'stderr', diff --git a/ale_linters/less/stylelint.vim b/ale_linters/less/stylelint.vim index 8e16a098..479808c2 100644 --- a/ale_linters/less/stylelint.vim +++ b/ale_linters/less/stylelint.vim @@ -4,24 +4,17 @@ call ale#Set('less_stylelint_executable', 'stylelint') call ale#Set('less_stylelint_options', '') call ale#Set('less_stylelint_use_global', get(g:, 'ale_use_global_executables', 0)) -function! ale_linters#less#stylelint#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'less_stylelint', [ - \ 'node_modules/.bin/stylelint', - \]) -endfunction - function! ale_linters#less#stylelint#GetCommand(buffer) abort - let l:executable = ale_linters#less#stylelint#GetExecutable(a:buffer) let l:options = ale#Var(a:buffer, 'less_stylelint_options') - return ale#Escape(l:executable) - \ . (!empty(l:options) ? ' ' . l:options : '') - \ . ' --stdin-filename %s' + return '%e' . ale#Pad(l:options) . ' --stdin-filename %s' endfunction call ale#linter#Define('less', { \ 'name': 'stylelint', -\ 'executable_callback': 'ale_linters#less#stylelint#GetExecutable', +\ 'executable_callback': ale#node#FindExecutableFunc('less_stylelint', [ +\ 'node_modules/.bin/stylelint', +\ ]), \ 'command_callback': 'ale_linters#less#stylelint#GetCommand', \ 'callback': 'ale#handlers#css#HandleStyleLintFormat', \}) diff --git a/ale_linters/llvm/llc.vim b/ale_linters/llvm/llc.vim index 15201cbe..044f8c44 100644 --- a/ale_linters/llvm/llc.vim +++ b/ale_linters/llvm/llc.vim @@ -3,21 +3,11 @@ call ale#Set('llvm_llc_executable', 'llc') -function! ale_linters#llvm#llc#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'llvm_llc_executable') -endfunction - -function! ale_linters#llvm#llc#GetCommand(buffer) abort - return ale#Escape(ale_linters#llvm#llc#GetExecutable(a:buffer)) - \ . ' -filetype=null -o=' . g:ale#util#nul_file -endfunction - function! ale_linters#llvm#llc#HandleErrors(buffer, lines) abort " Handle '{path}: {file}:{line}:{col}: error: {message}' format let l:pattern = '\v^[a-zA-Z]?:?[^:]+: [^:]+:(\d+):(\d+): (.+)$' - let l:matches = ale#util#GetMatches(a:lines, l:pattern) - return map(l:matches, "{ + return map(ale#util#GetMatches(a:lines, l:pattern), "{ \ 'lnum': str2nr(v:val[1]), \ 'col': str2nr(v:val[2]), \ 'text': v:val[3], @@ -27,8 +17,8 @@ endfunction call ale#linter#Define('llvm', { \ 'name': 'llc', -\ 'executable_callback': 'ale_linters#llvm#llc#GetExecutable', +\ 'executable_callback': ale#VarFunc('llvm_llc_executable'), \ 'output_stream': 'stderr', -\ 'command_callback': 'ale_linters#llvm#llc#GetCommand', +\ 'command_callback': {-> '%e -filetype=null -o=' . g:ale#util#nul_file}, \ 'callback': 'ale_linters#llvm#llc#HandleErrors', \}) diff --git a/ale_linters/lua/luac.vim b/ale_linters/lua/luac.vim index 4a6bb403..bca2cd8d 100644 --- a/ale_linters/lua/luac.vim +++ b/ale_linters/lua/luac.vim @@ -3,15 +3,6 @@ call ale#Set('lua_luac_executable', 'luac') -function! ale_linters#lua#luac#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'lua_luac_executable') -endfunction - -function! ale_linters#lua#luac#GetCommand(buffer) abort - let l:executable = ale_linters#lua#luac#GetExecutable(a:buffer) - return ale#Escape(l:executable) . ' -p - ' -endfunction - function! ale_linters#lua#luac#Handle(buffer, lines) abort " Matches patterns line the following: " @@ -33,8 +24,8 @@ endfunction call ale#linter#Define('lua', { \ 'name': 'luac', -\ 'executable_callback': 'ale_linters#lua#luac#GetExecutable', -\ 'command_callback': 'ale_linters#lua#luac#GetCommand', +\ 'executable_callback': ale#VarFunc('lua_luac_executable'), +\ 'command': '%e -p -', \ 'output_stream': 'stderr', \ 'callback': 'ale_linters#lua#luac#Handle', \}) diff --git a/ale_linters/lua/luacheck.vim b/ale_linters/lua/luacheck.vim index 725153c6..669103b8 100644 --- a/ale_linters/lua/luacheck.vim +++ b/ale_linters/lua/luacheck.vim @@ -1,19 +1,11 @@ " Author: Sol Bekic https://github.com/s-ol " Description: luacheck linter for lua files -let g:ale_lua_luacheck_executable = -\ get(g:, 'ale_lua_luacheck_executable', 'luacheck') - -let g:ale_lua_luacheck_options = -\ get(g:, 'ale_lua_luacheck_options', '') - -function! ale_linters#lua#luacheck#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'lua_luacheck_executable') -endfunction +call ale#Set('lua_luacheck_executable', 'luacheck') +call ale#Set('lua_luacheck_options', '') function! ale_linters#lua#luacheck#GetCommand(buffer) abort - return ale#Escape(ale_linters#lua#luacheck#GetExecutable(a:buffer)) - \ . ' ' . ale#Var(a:buffer, 'lua_luacheck_options') + return '%e' . ale#Pad(ale#Var(a:buffer, 'lua_luacheck_options')) \ . ' --formatter plain --codes --filename %s -' endfunction @@ -46,7 +38,7 @@ endfunction call ale#linter#Define('lua', { \ 'name': 'luacheck', -\ 'executable_callback': 'ale_linters#lua#luacheck#GetExecutable', +\ 'executable_callback': ale#VarFunc('lua_luacheck_executable'), \ 'command_callback': 'ale_linters#lua#luacheck#GetCommand', \ 'callback': 'ale_linters#lua#luacheck#Handle', \}) diff --git a/ale_linters/make/checkmake.vim b/ale_linters/make/checkmake.vim index 63c35db3..5ebdf91e 100644 --- a/ale_linters/make/checkmake.vim +++ b/ale_linters/make/checkmake.vim @@ -13,6 +13,7 @@ function! ale_linters#make#checkmake#Handle(buffer, lines) abort \ 'text': l:match[3], \}) endfor + return l:output endfunction diff --git a/ale_linters/markdown/remark_lint.vim b/ale_linters/markdown/remark_lint.vim index d9c2efb6..4f8d48fa 100644 --- a/ale_linters/markdown/remark_lint.vim +++ b/ale_linters/markdown/remark_lint.vim @@ -5,19 +5,10 @@ call ale#Set('markdown_remark_lint_executable', 'remark') call ale#Set('markdown_remark_lint_use_global', get(g:, 'ale_use_global_executables', 0)) call ale#Set('markdown_remark_lint_options', '') -function! ale_linters#markdown#remark_lint#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'markdown_remark_lint', [ - \ 'node_modules/.bin/remark', - \]) -endfunction - function! ale_linters#markdown#remark_lint#GetCommand(buffer) abort - let l:executable = ale_linters#markdown#remark_lint#GetExecutable(a:buffer) let l:options = ale#Var(a:buffer, 'markdown_remark_lint_options') - return ale#node#Executable(a:buffer, l:executable) - \ . (!empty(l:options) ? ' ' . l:options : '') - \ . ' --no-stdout --no-color' + return '%e' . ale#Pad(l:options) . ' --no-stdout --no-color' endfunction function! ale_linters#markdown#remark_lint#Handle(buffer, lines) abort @@ -33,10 +24,12 @@ function! ale_linters#markdown#remark_lint#Handle(buffer, lines) abort \ 'type': l:match[6] is# 'error' ? 'E' : 'W', \ 'text': l:match[7], \} + if l:match[3] isnot# '' let l:item.end_lnum = l:match[4] + 0 let l:item.end_col = l:match[5] + 0 endif + call add(l:output, l:item) endfor @@ -46,7 +39,9 @@ endfunction call ale#linter#Define('markdown', { \ 'name': 'remark_lint', \ 'aliases': ['remark-lint'], -\ 'executable_callback': 'ale_linters#markdown#remark_lint#GetExecutable', +\ 'executable_callback': ale#node#FindExecutableFunc('markdown_remark_lint', [ +\ 'node_modules/.bin/remark', +\ ]), \ 'command_callback': 'ale_linters#markdown#remark_lint#GetCommand', \ 'callback': 'ale_linters#markdown#remark_lint#Handle', \ 'output_stream': 'stderr', diff --git a/ale_linters/matlab/mlint.vim b/ale_linters/matlab/mlint.vim index 32766334..3435045e 100644 --- a/ale_linters/matlab/mlint.vim +++ b/ale_linters/matlab/mlint.vim @@ -1,18 +1,7 @@ " Author: awlayton <alex@layton.in> " Description: mlint for MATLAB files -let g:ale_matlab_mlint_executable = -\ get(g:, 'ale_matlab_mlint_executable', 'mlint') - -function! ale_linters#matlab#mlint#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'matlab_mlint_executable') -endfunction - -function! ale_linters#matlab#mlint#GetCommand(buffer) abort - let l:executable = ale_linters#matlab#mlint#GetExecutable(a:buffer) - - return l:executable . ' -id %t' -endfunction +call ale#Set('matlab_mlint_executable', 'mlint') function! ale_linters#matlab#mlint#Handle(buffer, lines) abort " Matches patterns like the following: @@ -48,8 +37,8 @@ endfunction call ale#linter#Define('matlab', { \ 'name': 'mlint', -\ 'executable_callback': 'ale_linters#matlab#mlint#GetExecutable', -\ 'command_callback': 'ale_linters#matlab#mlint#GetCommand', +\ 'executable_callback': ale#VarFunc('matlab_mlint_executable'), +\ 'command': '%e -id %t', \ 'output_stream': 'stderr', \ 'callback': 'ale_linters#matlab#mlint#Handle', \}) diff --git a/ale_linters/mercury/mmc.vim b/ale_linters/mercury/mmc.vim index c7bfc59d..76d357f0 100644 --- a/ale_linters/mercury/mmc.vim +++ b/ale_linters/mercury/mmc.vim @@ -4,16 +4,11 @@ call ale#Set('mercury_mmc_executable', 'mmc') call ale#Set('mercury_mmc_options', '--make --output-compile-error-lines 100') -function! ale_linters#mercury#mmc#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'mercury_mmc_executable') -endfunction - function! ale_linters#mercury#mmc#GetCommand(buffer) abort let l:module_name = expand('#' . a:buffer . ':t:r') return ale#path#BufferCdString(a:buffer) - \ . ale_linters#mercury#mmc#GetExecutable(a:buffer) - \ . ' --errorcheck-only ' + \ . '%e --errorcheck-only ' \ . ale#Var(a:buffer, 'mercury_mmc_options') \ . ' ' . l:module_name endfunction @@ -38,7 +33,7 @@ endfunction call ale#linter#Define('mercury', { \ 'name': 'mmc', \ 'output_stream': 'stderr', -\ 'executable_callback': 'ale_linters#mercury#mmc#GetExecutable', +\ 'executable_callback': ale#VarFunc('mercury_mmc_executable'), \ 'command_callback': 'ale_linters#mercury#mmc#GetCommand', \ 'callback': 'ale_linters#mercury#mmc#Handle', \ 'lint_file': 1, diff --git a/ale_linters/nasm/nasm.vim b/ale_linters/nasm/nasm.vim index 77d57e18..cb2119a6 100644 --- a/ale_linters/nasm/nasm.vim +++ b/ale_linters/nasm/nasm.vim @@ -4,32 +4,23 @@ call ale#Set('nasm_nasm_executable', 'nasm') call ale#Set('nasm_nasm_options', '') -function! ale_linters#nasm#nasm#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'nasm_nasm_executable') -endfunction - -function! ale_linters#nasm#nasm#GetOptions(buffer) abort - return ale#Var(a:buffer, 'nasm_nasm_options') -endfunction - function! ale_linters#nasm#nasm#GetCommand(buffer) abort - " Note that NASM require a trailing slash to the -I option. - let l:executable = ale#Escape(ale_linters#nasm#nasm#GetExecutable(a:buffer)) + " Note that NASM requires a trailing slash for the -I option. let l:separator = has('win32') ? '\' : '/' - let l:path = ale#Escape(fnamemodify(bufname(a:buffer), ':p:h') . l:separator) - let l:options = ale_linters#nasm#nasm#GetOptions(a:buffer) + let l:path = fnamemodify(bufname(a:buffer), ':p:h') . l:separator + let l:output_null = has('win32') ? 'NUL' : '/dev/null' - return l:executable - \ . ' -X gnu' - \ . ' -I ' . l:path - \ . ' ' . l:options + return '%e -X gnu -I ' . ale#Escape(l:path) + \ . ale#Pad(ale#Var(a:buffer, 'nasm_nasm_options')) \ . ' %s' + \ . ' -o ' . l:output_null endfunction function! ale_linters#nasm#nasm#Handle(buffer, lines) abort " Note that we treat 'fatal' as errors. let l:pattern = '^.\+:\(\d\+\): \([^:]\+\): \(.\+\)$' let l:output = [] + for l:match in ale#util#GetMatches(a:lines, l:pattern) call add(l:output, { \ 'lnum': l:match[1] + 0, @@ -37,6 +28,7 @@ function! ale_linters#nasm#nasm#Handle(buffer, lines) abort \ 'text': l:match[3], \}) endfor + return l:output endfunction @@ -44,7 +36,7 @@ call ale#linter#Define('nasm', { \ 'name': 'nasm', \ 'output_stream': 'stderr', \ 'lint_file': 1, -\ 'executable_callback': 'ale_linters#nasm#nasm#GetExecutable', +\ 'executable_callback': ale#VarFunc('nasm_nasm_executable'), \ 'command_callback': 'ale_linters#nasm#nasm#GetCommand', \ 'callback': 'ale_linters#nasm#nasm#Handle', \}) diff --git a/ale_linters/objc/ccls.vim b/ale_linters/objc/ccls.vim new file mode 100644 index 00000000..0aa6a5e5 --- /dev/null +++ b/ale_linters/objc/ccls.vim @@ -0,0 +1,14 @@ +" Author: Ye Jingchen <ye.jingchen@gmail.com>, Ben Falconer <ben@falconers.me.uk>, jtalowell <jtalowell@protonmail.com> +" Description: A language server for Objective-C + +call ale#Set('objc_ccls_executable', 'ccls') +call ale#Set('objc_ccls_init_options', {}) + +call ale#linter#Define('objc', { +\ 'name': 'ccls', +\ 'lsp': 'stdio', +\ 'executable_callback': ale#VarFunc('objc_ccls_executable'), +\ 'command': '%e', +\ 'project_root_callback': 'ale#handlers#ccls#GetProjectRoot', +\ 'initialization_options_callback': ale#VarFunc('objc_ccls_init_options'), +\}) diff --git a/ale_linters/objc/clang.vim b/ale_linters/objc/clang.vim index f4725a0e..4e80ac5c 100644 --- a/ale_linters/objc/clang.vim +++ b/ale_linters/objc/clang.vim @@ -19,5 +19,5 @@ call ale#linter#Define('objc', { \ 'output_stream': 'stderr', \ 'executable': 'clang', \ 'command_callback': 'ale_linters#objc#clang#GetCommand', -\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', +\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes', \}) diff --git a/ale_linters/objc/clangd.vim b/ale_linters/objc/clangd.vim new file mode 100644 index 00000000..f090e6ce --- /dev/null +++ b/ale_linters/objc/clangd.vim @@ -0,0 +1,23 @@ +" Author: Andrey Melentyev <andrey.melentyev@protonmail.com> +" Description: Clangd language server + +call ale#Set('objc_clangd_executable', 'clangd') +call ale#Set('objc_clangd_options', '') + +function! ale_linters#objc#clangd#GetProjectRoot(buffer) abort + let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json') + + return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' +endfunction + +function! ale_linters#objc#clangd#GetCommand(buffer) abort + return '%e' . ale#Pad(ale#Var(a:buffer, 'objc_clangd_options')) +endfunction + +call ale#linter#Define('objc', { +\ 'name': 'clangd', +\ 'lsp': 'stdio', +\ 'executable_callback': ale#VarFunc('objc_clangd_executable'), +\ 'command_callback': 'ale_linters#objc#clangd#GetCommand', +\ 'project_root_callback': 'ale_linters#objc#clangd#GetProjectRoot', +\}) diff --git a/ale_linters/objcpp/clang.vim b/ale_linters/objcpp/clang.vim index 0e9cefe9..d1474f17 100644 --- a/ale_linters/objcpp/clang.vim +++ b/ale_linters/objcpp/clang.vim @@ -19,5 +19,5 @@ call ale#linter#Define('objcpp', { \ 'output_stream': 'stderr', \ 'executable': 'clang++', \ 'command_callback': 'ale_linters#objcpp#clang#GetCommand', -\ 'callback': 'ale#handlers#gcc#HandleGCCFormat', +\ 'callback': 'ale#handlers#gcc#HandleGCCFormatWithIncludes', \}) diff --git a/ale_linters/objcpp/clangd.vim b/ale_linters/objcpp/clangd.vim new file mode 100644 index 00000000..a09753be --- /dev/null +++ b/ale_linters/objcpp/clangd.vim @@ -0,0 +1,23 @@ +" Author: Andrey Melentyev <andrey.melentyev@protonmail.com> +" Description: Clangd language server + +call ale#Set('objcpp_clangd_executable', 'clangd') +call ale#Set('objcpp_clangd_options', '') + +function! ale_linters#objcpp#clangd#GetProjectRoot(buffer) abort + let l:project_root = ale#path#FindNearestFile(a:buffer, 'compile_commands.json') + + return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' +endfunction + +function! ale_linters#objcpp#clangd#GetCommand(buffer) abort + return '%e' . ale#Pad(ale#Var(a:buffer, 'objcpp_clangd_options')) +endfunction + +call ale#linter#Define('objcpp', { +\ 'name': 'clangd', +\ 'lsp': 'stdio', +\ 'executable_callback': ale#VarFunc('objcpp_clangd_executable'), +\ 'command_callback': 'ale_linters#objcpp#clangd#GetCommand', +\ 'project_root_callback': 'ale_linters#objcpp#clangd#GetProjectRoot', +\}) diff --git a/ale_linters/perl/perl.vim b/ale_linters/perl/perl.vim index 1b9aa95e..1cb20fa7 100644 --- a/ale_linters/perl/perl.vim +++ b/ale_linters/perl/perl.vim @@ -1,20 +1,11 @@ " Author: Vincent Lequertier <https://github.com/SkySymbol> " Description: This file adds support for checking perl syntax -let g:ale_perl_perl_executable = -\ get(g:, 'ale_perl_perl_executable', 'perl') - -let g:ale_perl_perl_options = -\ get(g:, 'ale_perl_perl_options', '-c -Mwarnings -Ilib') - -function! ale_linters#perl#perl#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'perl_perl_executable') -endfunction +call ale#Set('perl_perl_executable', 'perl') +call ale#Set('perl_perl_options', '-c -Mwarnings -Ilib') function! ale_linters#perl#perl#GetCommand(buffer) abort - return ale#Escape(ale_linters#perl#perl#GetExecutable(a:buffer)) - \ . ' ' . ale#Var(a:buffer, 'perl_perl_options') - \ . ' %t' + return '%e' . ale#Pad(ale#Var(a:buffer, 'perl_perl_options')) . ' %t' endfunction let s:begin_failed_skip_pattern = '\v' . join([ @@ -23,11 +14,16 @@ let s:begin_failed_skip_pattern = '\v' . join([ \], '|') function! ale_linters#perl#perl#Handle(buffer, lines) abort + if empty(a:lines) + return [] + endif + let l:pattern = '\(.\+\) at \(.\+\) line \(\d\+\)' let l:output = [] let l:basename = expand('#' . a:buffer . ':t') let l:type = 'E' + if a:lines[-1] =~# 'syntax OK' let l:type = 'W' endif @@ -61,7 +57,7 @@ endfunction call ale#linter#Define('perl', { \ 'name': 'perl', -\ 'executable_callback': 'ale_linters#perl#perl#GetExecutable', +\ 'executable_callback': ale#VarFunc('perl_perl_executable'), \ 'output_stream': 'both', \ 'command_callback': 'ale_linters#perl#perl#GetCommand', \ 'callback': 'ale_linters#perl#perl#Handle', diff --git a/ale_linters/perl/perlcritic.vim b/ale_linters/perl/perlcritic.vim index e91c8a03..8619a404 100644 --- a/ale_linters/perl/perlcritic.vim +++ b/ale_linters/perl/perlcritic.vim @@ -1,21 +1,10 @@ " Author: Vincent Lequertier <https://github.com/SkySymbol>, Chris Weyl <cweyl@alumni.drew.edu> " Description: This file adds support for checking perl with perl critic -let g:ale_perl_perlcritic_executable = -\ get(g:, 'ale_perl_perlcritic_executable', 'perlcritic') - -let g:ale_perl_perlcritic_profile = -\ get(g:, 'ale_perl_perlcritic_profile', '.perlcriticrc') - -let g:ale_perl_perlcritic_options = -\ get(g:, 'ale_perl_perlcritic_options', '') - -let g:ale_perl_perlcritic_showrules = -\ get(g:, 'ale_perl_perlcritic_showrules', 0) - -function! ale_linters#perl#perlcritic#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'perl_perlcritic_executable') -endfunction +call ale#Set('perl_perlcritic_executable', 'perlcritic') +call ale#Set('perl_perlcritic_profile', '.perlcriticrc') +call ale#Set('perl_perlcritic_options', '') +call ale#Set('perl_perlcritic_showrules', 0) function! ale_linters#perl#perlcritic#GetProfile(buffer) abort " first see if we've been overridden @@ -39,11 +28,11 @@ function! ale_linters#perl#perlcritic#GetCommand(buffer) abort let l:profile = ale_linters#perl#perlcritic#GetProfile(a:buffer) let l:options = ale#Var(a:buffer, 'perl_perlcritic_options') - return ale#Escape(ale_linters#perl#perlcritic#GetExecutable(a:buffer)) + return '%e' \ . ' --verbose ' . ale#Escape(l:critic_verbosity) \ . ' --nocolor' \ . (!empty(l:profile) ? ' --profile ' . ale#Escape(l:profile) : '') - \ . (!empty(l:options) ? ' ' . l:options : '') + \ . ale#Pad(l:options) endfunction @@ -66,7 +55,7 @@ endfunction call ale#linter#Define('perl', { \ 'name': 'perlcritic', \ 'output_stream': 'stdout', -\ 'executable_callback': 'ale_linters#perl#perlcritic#GetExecutable', +\ 'executable_callback': ale#VarFunc('perl_perlcritic_executable'), \ 'command_callback': 'ale_linters#perl#perlcritic#GetCommand', \ 'callback': 'ale_linters#perl#perlcritic#Handle', \}) diff --git a/ale_linters/perl6/perl6.vim b/ale_linters/perl6/perl6.vim new file mode 100644 index 00000000..b33a0c51 --- /dev/null +++ b/ale_linters/perl6/perl6.vim @@ -0,0 +1,166 @@ +" Author:Travis Gibson <https://github.com/Garland-g> +" Description: This file adds support for checking perl6 syntax + +let g:ale_perl6_perl6_executable = +\ get(g:, 'ale_perl6_perl6_executable', 'perl6') + +let g:ale_perl6_perl6_options = +\ get(g:, 'ale_perl6_perl6_options', '-c -Ilib') + +let $PERL6_EXCEPTIONS_HANDLER = 'JSON' + +let $RAKUDO_ERROR_COLOR = 0 + +function! ale_linters#perl6#perl6#GetExecutable(buffer) abort + return ale#Var(a:buffer, 'perl6_perl6_executable') +endfunction + +function! ale_linters#perl6#perl6#GetCommand(buffer) abort + return ale_linters#perl6#perl6#GetExecutable(a:buffer) + \ . ' ' . ale#Var(a:buffer, 'perl6_perl6_options') + \ . ' %t' +endfunction + +function! ale_linters#perl6#perl6#ExtractError(dict, item, type, buffer) abort + let l:file = '' + let l:line = 1 + let l:column = '' + let l:text = '' + let l:pre = '' + let l:counter = 2 + let l:end_line = '' + let l:linepatternmessage = 'at\s\+line\s\+\(\d\+\)' + + if has_key(a:dict[a:item], 'filename') && !empty(a:dict[a:item]['filename']) + let l:file = a:dict[a:item]['filename'] + endif + + if has_key(a:dict[a:item], 'line') && !empty(a:dict[a:item]['line']) + let l:line = a:dict[a:item]['line'] + let l:counter -= 1 + endif + + if has_key(a:dict[a:item], 'column') && !empty(a:dict[a:item]['column']) + let l:column = a:dict[a:item]['column'] + endif + + if has_key(a:dict[a:item], 'message') && !empty(a:dict[a:item]['message']) + let l:text = substitute(a:dict[a:item]['message'], '\s*\n\s*', ' ', 'g') + let l:counter -= 1 + endif + + if has_key(a:dict[a:item], 'line-real') && !empty(a:dict[a:item]['line-real']) + let l:end_line = l:line + let l:line = a:dict[a:item]['line-real'] + endif + + for l:match in ale#util#GetMatches(l:text, l:linepatternmessage) + let l:line = l:match[1] + let l:counter -= 1 + endfor + +" Currently, filenames and line numbers are not always given in the error output + if l:counter < 2 + \&& ( ale#path#IsBufferPath(a:buffer, l:file) || l:file is# '' ) + return { + \ 'lnum': '' . l:line, + \ 'text': l:text, + \ 'type': a:type, + \ 'col': l:column, + \ 'end_lnum': l:end_line, + \ 'code': a:item, + \} + endif + + return '' +endfunction + +function! ale_linters#perl6#perl6#Handle(buffer, lines) abort + let l:output = [] + + if empty(a:lines) + return l:output + endif + + if a:lines[0] is# 'Syntax OK' + return l:output + endif + + try + let l:json = json_decode(join(a:lines, '')) + catch /E474/ + call add(l:output, { + \ 'lnum': '1', + \ 'text': 'Received output in the default Perl6 error format. See :ALEDetail for details', + \ 'detail': join(a:lines, "\n"), + \ 'type': 'W', + \ }) + + return l:output + endtry + + if type(l:json) is v:t_dict + for l:key in keys(l:json) + if has_key(l:json[l:key], 'sorrows') && + \ has_key(l:json[l:key], 'worries') + if !empty(l:json[l:key]['sorrows']) + for l:dictionary in get(l:json[l:key], 'sorrows') + for l:item in keys(l:dictionary) + let l:result = + \ ale_linters#perl6#perl6#ExtractError( + \ l:dictionary, + \ l:item, + \ 'E', + \ a:buffer, + \ ) + + if l:result isnot# '' + call add(l:output, l:result) + endif + endfor + endfor + endif + + if !empty(l:json[l:key]['worries']) + for l:dictionary in get(l:json[l:key], 'worries') + for l:item in keys(l:dictionary) + let l:result = + \ ale_linters#perl6#perl6#ExtractError( + \ l:dictionary, + \ l:item, + \ 'W', + \ a:buffer, + \ ) + + if l:result isnot# '' + call add(l:output, l:result) + endif + endfor + endfor + endif + else + let l:result = ale_linters#perl6#perl6#ExtractError( + \ l:json, + \ l:key, + \ 'E', + \ a:buffer, + \ ) + + if l:result isnot# '' + call add(l:output, l:result) + endif + endif + endfor + endif + + return l:output +endfunction + +call ale#linter#Define('perl6', { +\ 'name': 'perl6', +\ 'executable_callback': 'ale_linters#perl6#perl6#GetExecutable', +\ 'output_stream': 'both', +\ 'command_callback': 'ale_linters#perl6#perl6#GetCommand', +\ 'callback': 'ale_linters#perl6#perl6#Handle', +\}) + diff --git a/ale_linters/php/hack.vim b/ale_linters/php/hack.vim deleted file mode 100644 index 77d3a588..00000000 --- a/ale_linters/php/hack.vim +++ /dev/null @@ -1,28 +0,0 @@ -" Author: Zefei Xuan <https://github.com/zefei> -" Description: Hack type checking (http://hacklang.org/) - -function! ale_linters#php#hack#Handle(buffer, lines) abort - let l:pattern = '^\(.*\):\(\d\+\):\(\d\+\),\(\d\+\): \(.\+])\)$' - let l:output = [] - - for l:match in ale#util#GetMatches(a:lines, l:pattern) - if a:buffer != bufnr(l:match[1]) - continue - endif - - call add(l:output, { - \ 'lnum': l:match[2] + 0, - \ 'col': l:match[3] + 0, - \ 'text': l:match[5], - \}) - endfor - - return l:output -endfunction - -call ale#linter#Define('php', { -\ 'name': 'hack', -\ 'executable': 'hh_client', -\ 'command': 'hh_client --retries 0 --retry-if-init false', -\ 'callback': 'ale_linters#php#hack#Handle', -\}) diff --git a/ale_linters/php/langserver.vim b/ale_linters/php/langserver.vim index 38b42df9..ca91db4c 100644 --- a/ale_linters/php/langserver.vim +++ b/ale_linters/php/langserver.vim @@ -4,16 +4,6 @@ call ale#Set('php_langserver_executable', 'php-language-server.php') call ale#Set('php_langserver_use_global', get(g:, 'ale_use_global_executables', 0)) -function! ale_linters#php#langserver#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'php_langserver', [ - \ 'vendor/bin/php-language-server.php', - \]) -endfunction - -function! ale_linters#php#langserver#GetCommand(buffer) abort - return 'php ' . ale#Escape(ale_linters#php#langserver#GetExecutable(a:buffer)) -endfunction - function! ale_linters#php#langserver#GetProjectRoot(buffer) abort let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git') @@ -23,7 +13,9 @@ endfunction call ale#linter#Define('php', { \ 'name': 'langserver', \ 'lsp': 'stdio', -\ 'executable_callback': 'ale_linters#php#langserver#GetExecutable', -\ 'command_callback': 'ale_linters#php#langserver#GetCommand', +\ 'executable_callback': ale#node#FindExecutableFunc('php_langserver', [ +\ 'vendor/bin/php-language-server.php', +\ ]), +\ 'command': 'php %e', \ 'project_root_callback': 'ale_linters#php#langserver#GetProjectRoot', \}) diff --git a/ale_linters/php/php.vim b/ale_linters/php/php.vim index 6470383b..5d87196c 100644 --- a/ale_linters/php/php.vim +++ b/ale_linters/php/php.vim @@ -1,6 +1,8 @@ " Author: Spencer Wood <https://github.com/scwood>, Adriaan Zonnenberg <amz@adriaan.xyz> " Description: This file adds support for checking PHP with php-cli +call ale#Set('php_php_executable', 'php') + function! ale_linters#php#php#Handle(buffer, lines) abort " Matches patterns like the following: " @@ -30,8 +32,8 @@ endfunction call ale#linter#Define('php', { \ 'name': 'php', -\ 'executable': 'php', +\ 'executable_callback': ale#VarFunc('php_php_executable'), \ 'output_stream': 'stdout', -\ 'command': 'php -l -d error_reporting=E_ALL -d display_errors=1 -d log_errors=0 --', +\ 'command': '%e -l -d error_reporting=E_ALL -d display_errors=1 -d log_errors=0 --', \ 'callback': 'ale_linters#php#php#Handle', \}) diff --git a/ale_linters/php/phpcs.vim b/ale_linters/php/phpcs.vim index faf8ad55..408c2652 100644 --- a/ale_linters/php/phpcs.vim +++ b/ale_linters/php/phpcs.vim @@ -3,26 +3,20 @@ let g:ale_php_phpcs_standard = get(g:, 'ale_php_phpcs_standard', '') +call ale#Set('php_phpcs_options', '') call ale#Set('php_phpcs_executable', 'phpcs') call ale#Set('php_phpcs_use_global', get(g:, 'ale_use_global_executables', 0)) -function! ale_linters#php#phpcs#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'php_phpcs', [ - \ 'vendor/bin/phpcs', - \ 'phpcs' - \]) -endfunction - function! ale_linters#php#phpcs#GetCommand(buffer) abort - let l:executable = ale_linters#php#phpcs#GetExecutable(a:buffer) - let l:standard = ale#Var(a:buffer, 'php_phpcs_standard') let l:standard_option = !empty(l:standard) \ ? '--standard=' . l:standard \ : '' + let l:options = ale#Var(a:buffer, 'php_phpcs_options') - return ale#Escape(l:executable) - \ . ' -s --report=emacs --stdin-path=%s ' . l:standard_option + return '%e -s --report=emacs --stdin-path=%s' + \ . ale#Pad(l:standard_option) + \ . ale#Pad(l:options) endfunction function! ale_linters#php#phpcs#Handle(buffer, lines) abort @@ -50,7 +44,10 @@ endfunction call ale#linter#Define('php', { \ 'name': 'phpcs', -\ 'executable_callback': 'ale_linters#php#phpcs#GetExecutable', +\ 'executable_callback': ale#node#FindExecutableFunc('php_phpcs', [ +\ 'vendor/bin/phpcs', +\ 'phpcs' +\ ]), \ 'command_callback': 'ale_linters#php#phpcs#GetCommand', \ 'callback': 'ale_linters#php#phpcs#Handle', \}) diff --git a/ale_linters/php/phpmd.vim b/ale_linters/php/phpmd.vim index e9450752..65f1cc3c 100644 --- a/ale_linters/php/phpmd.vim +++ b/ale_linters/php/phpmd.vim @@ -6,16 +6,9 @@ let g:ale_php_phpmd_executable = get(g:, 'ale_php_phpmd_executable', 'phpmd') " Set to change the ruleset let g:ale_php_phpmd_ruleset = get(g:, 'ale_php_phpmd_ruleset', 'cleancode,codesize,controversial,design,naming,unusedcode') -function! ale_linters#php#phpmd#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'php_phpmd_executable') -endfunction - function! ale_linters#php#phpmd#GetCommand(buffer) abort - let l:executable = ale_linters#php#phpmd#GetExecutable(a:buffer) - - return ale#Escape(l:executable) - \ . ' %s text ' - \ . ale#Var(a:buffer, 'php_phpmd_ruleset') + return '%e %s text' + \ . ale#Pad(ale#Var(a:buffer, 'php_phpmd_ruleset')) \ . ' --ignore-violations-on-exit %t' endfunction @@ -39,7 +32,7 @@ endfunction call ale#linter#Define('php', { \ 'name': 'phpmd', -\ 'executable_callback': 'ale_linters#php#phpmd#GetExecutable', +\ 'executable_callback': ale#VarFunc('php_phpmd_executable'), \ 'command_callback': 'ale_linters#php#phpmd#GetCommand', \ 'callback': 'ale_linters#php#phpmd#Handle', \}) diff --git a/ale_linters/php/phpstan.vim b/ale_linters/php/phpstan.vim index 24762086..1c831e1b 100644 --- a/ale_linters/php/phpstan.vim +++ b/ale_linters/php/phpstan.vim @@ -10,18 +10,36 @@ function! ale_linters#php#phpstan#GetExecutable(buffer) abort return ale#Var(a:buffer, 'php_phpstan_executable') endfunction -function! ale_linters#php#phpstan#GetCommand(buffer) abort +function! ale_linters#php#phpstan#VersionCheck(buffer) abort let l:executable = ale_linters#php#phpstan#GetExecutable(a:buffer) + " If we have previously stored the version number in a cache, then + " don't look it up again. + if ale#semver#HasVersion(l:executable) + " Returning an empty string skips this command. + return '' + endif + + let l:executable = ale#Escape(l:executable) + + return l:executable . ' --version' +endfunction + +function! ale_linters#php#phpstan#GetCommand(buffer, version_output) abort let l:configuration = ale#Var(a:buffer, 'php_phpstan_configuration') let l:configuration_option = !empty(l:configuration) \ ? ' -c ' . l:configuration \ : '' - return ale#Escape(l:executable) - \ . ' analyze -l' + let l:executable = ale_linters#php#phpstan#GetExecutable(a:buffer) + let l:version = ale#semver#GetVersion(l:executable, a:version_output) + let l:error_format = ale#semver#GTE(l:version, [0, 10, 3]) + \ ? ' --error-format raw' + \ : ' --errorFormat raw' + + return '%e analyze -l' \ . ale#Var(a:buffer, 'php_phpstan_level') - \ . ' --errorFormat raw' + \ . l:error_format \ . l:configuration_option \ . ' %s' endfunction @@ -48,6 +66,9 @@ endfunction call ale#linter#Define('php', { \ 'name': 'phpstan', \ 'executable_callback': 'ale_linters#php#phpstan#GetExecutable', -\ 'command_callback': 'ale_linters#php#phpstan#GetCommand', +\ 'command_chain': [ +\ {'callback': 'ale_linters#php#phpstan#VersionCheck'}, +\ {'callback': 'ale_linters#php#phpstan#GetCommand'}, +\ ], \ 'callback': 'ale_linters#php#phpstan#Handle', \}) diff --git a/ale_linters/php/psalm.vim b/ale_linters/php/psalm.vim new file mode 100644 index 00000000..dce59178 --- /dev/null +++ b/ale_linters/php/psalm.vim @@ -0,0 +1,21 @@ +" Author: Matt Brown <https://github.com/muglug> +" Description: plugin for Psalm, static analyzer for PHP + +call ale#Set('psalm_langserver_executable', 'psalm-language-server') +call ale#Set('psalm_langserver_use_global', get(g:, 'ale_use_global_executables', 0)) + +function! ale_linters#php#psalm#GetProjectRoot(buffer) abort + let l:git_path = ale#path#FindNearestDirectory(a:buffer, '.git') + + return !empty(l:git_path) ? fnamemodify(l:git_path, ':h:h') : '' +endfunction + +call ale#linter#Define('php', { +\ 'name': 'psalm', +\ 'lsp': 'stdio', +\ 'executable_callback': ale#node#FindExecutableFunc('psalm_langserver', [ +\ 'vendor/bin/psalm-language-server', +\ ]), +\ 'command': '%e', +\ 'project_root_callback': 'ale_linters#php#psalm#GetProjectRoot', +\}) diff --git a/ale_linters/pony/ponyc.vim b/ale_linters/pony/ponyc.vim index b3329053..19e7e828 100644 --- a/ale_linters/pony/ponyc.vim +++ b/ale_linters/pony/ponyc.vim @@ -3,19 +3,14 @@ call ale#Set('pony_ponyc_executable', 'ponyc') call ale#Set('pony_ponyc_options', '--pass paint') -function! ale_linters#pony#ponyc#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'pony_ponyc_executable') -endfunction - function! ale_linters#pony#ponyc#GetCommand(buffer) abort - return ale#Escape(ale_linters#pony#ponyc#GetExecutable(a:buffer)) - \ . ' ' . ale#Var(a:buffer, 'pony_ponyc_options') + return '%e' . ale#Pad(ale#Var(a:buffer, 'pony_ponyc_options')) endfunction call ale#linter#Define('pony', { \ 'name': 'ponyc', \ 'output_stream': 'stderr', -\ 'executable_callback': 'ale_linters#pony#ponyc#GetExecutable', +\ 'executable_callback': ale#VarFunc('pony_ponyc_executable'), \ 'command_callback': 'ale_linters#pony#ponyc#GetCommand', \ 'callback': 'ale#handlers#pony#HandlePonycFormat', \}) diff --git a/ale_linters/prolog/swipl.vim b/ale_linters/prolog/swipl.vim new file mode 100644 index 00000000..401e52b6 --- /dev/null +++ b/ale_linters/prolog/swipl.vim @@ -0,0 +1,100 @@ +" Author: Takuya Fujiwara <tyru.exe@gmail.com> +" Description: swipl syntax / semantic check for Prolog files + +call ale#Set('prolog_swipl_executable', 'swipl') +call ale#Set('prolog_swipl_load', 'current_prolog_flag(argv, [File]), load_files(File, [sandboxed(true)]), halt.') +call ale#Set('prolog_swipl_timeout', 3) +call ale#Set('prolog_swipl_alarm', 'alarm(%t, (%h), _, [])') +call ale#Set('prolog_swipl_alarm_handler', 'writeln(user_error, "ERROR: Exceeded %t seconds, Please change g:prolog_swipl_timeout to modify the limit."), halt(1)') + +function! ale_linters#prolog#swipl#GetCommand(buffer) abort + let l:goals = ale#Var(a:buffer, 'prolog_swipl_load') + let l:goals = l:goals =~# '^\s*$' ? 'halt' : l:goals + let l:timeout = ale#Var(a:buffer, 'prolog_swipl_timeout') + 0 + + if l:timeout > 0 + let l:goals = s:GetAlarm(a:buffer, l:timeout) . ', ' . l:goals + endif + + return '%e -g ' . ale#Escape(l:goals) . ' -- %s' +endfunction + +function! s:GetAlarm(buffer, timeout) abort + let l:handler = ale#Var(a:buffer, 'prolog_swipl_alarm_handler') + let l:handler = s:Subst(l:handler, {'t': a:timeout}) + let l:alarm = ale#Var(a:buffer, 'prolog_swipl_alarm') + let l:alarm = s:Subst(l:alarm, {'t': a:timeout, 'h': l:handler}) + + return l:alarm +endfunction + +function! s:Subst(format, vars) abort + let l:vars = extend(copy(a:vars), {'%': '%'}) + + return substitute(a:format, '%\(.\)', '\=get(l:vars, submatch(1), "")', 'g') +endfunction + +function! ale_linters#prolog#swipl#Handle(buffer, lines) abort + let l:pattern = '\v^(ERROR|Warning)+%(:\s*[^:]+:(\d+)%(:(\d+))?)?:\s*(.*)$' + let l:output = [] + let l:i = 0 + + while l:i < len(a:lines) + let l:match = matchlist(a:lines[l:i], l:pattern) + + if empty(l:match) + let l:i += 1 + continue + endif + + let [l:i, l:text] = s:GetErrMsg(l:i, a:lines, l:match[4]) + let l:item = { + \ 'lnum': (l:match[2] + 0 ? l:match[2] + 0 : 1), + \ 'col': l:match[3] + 0, + \ 'text': l:text, + \ 'type': (l:match[1] is# 'ERROR' ? 'E' : 'W'), + \} + + if !s:Ignore(l:item) + call add(l:output, l:item) + endif + endwhile + + return l:output +endfunction + +" This returns [<next line number>, <error message string>] +function! s:GetErrMsg(i, lines, text) abort + if a:text !~# '^\s*$' + return [a:i + 1, a:text] + endif + + let l:i = a:i + 1 + let l:text = [] + + while l:i < len(a:lines) && a:lines[l:i] =~# '^\s' + call add(l:text, s:Trim(a:lines[l:i])) + let l:i += 1 + endwhile + + return [l:i, join(l:text, '. ')] +endfunction + +function! s:Trim(str) abort + return substitute(a:str, '\v^\s+|\s+$', '', 'g') +endfunction + +" Skip sandbox error which is caused by directives +" because what we want is syntactic or semantic check. +function! s:Ignore(item) abort + return a:item.type is# 'E' && + \ a:item.text =~# '\vNo permission to (call|directive|assert) sandboxed' +endfunction + +call ale#linter#Define('prolog', { +\ 'name': 'swipl', +\ 'output_stream': 'stderr', +\ 'executable_callback': ale#VarFunc('prolog_swipl_executable'), +\ 'command_callback': 'ale_linters#prolog#swipl#GetCommand', +\ 'callback': 'ale_linters#prolog#swipl#Handle', +\}) diff --git a/ale_linters/pug/puglint.vim b/ale_linters/pug/puglint.vim index 165e68b7..63208986 100644 --- a/ale_linters/pug/puglint.vim +++ b/ale_linters/pug/puglint.vim @@ -5,12 +5,6 @@ call ale#Set('pug_puglint_options', '') call ale#Set('pug_puglint_executable', 'pug-lint') call ale#Set('pug_puglint_use_global', get(g:, 'ale_use_global_executables', 0)) -function! ale_linters#pug#puglint#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'pug_puglint', [ - \ 'node_modules/.bin/pug-lint', - \]) -endfunction - function! s:FindConfig(buffer) abort for l:filename in [ \ '.pug-lintrc', @@ -29,19 +23,19 @@ function! s:FindConfig(buffer) abort endfunction function! ale_linters#pug#puglint#GetCommand(buffer) abort - let l:executable = ale_linters#pug#puglint#GetExecutable(a:buffer) let l:options = ale#Var(a:buffer, 'pug_puglint_options') let l:config = s:FindConfig(a:buffer) - return ale#Escape(l:executable) - \ . (!empty(l:options) ? ' ' . l:options : '') + return '%e' . ale#Pad(l:options) \ . (!empty(l:config) ? ' -c ' . ale#Escape(l:config) : '') \ . ' -r inline %t' endfunction call ale#linter#Define('pug', { \ 'name': 'puglint', -\ 'executable_callback': 'ale_linters#pug#puglint#GetExecutable', +\ 'executable_callback': ale#node#FindExecutableFunc('pug_puglint', [ +\ 'node_modules/.bin/pug-lint', +\ ]), \ 'output_stream': 'stderr', \ 'command_callback': 'ale_linters#pug#puglint#GetCommand', \ 'callback': 'ale#handlers#unix#HandleAsError', diff --git a/ale_linters/puppet/languageserver.vim b/ale_linters/puppet/languageserver.vim index 52880f32..a3060e65 100644 --- a/ale_linters/puppet/languageserver.vim +++ b/ale_linters/puppet/languageserver.vim @@ -3,21 +3,12 @@ call ale#Set('puppet_languageserver_executable', 'puppet-languageserver') -function! ale_linters#puppet#languageserver#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'puppet_languageserver_executable') -endfunction - -function! ale_linters#puppet#languageserver#GetCommand(buffer) abort - let l:exe = ale#Escape(ale_linters#puppet#languageserver#GetExecutable(a:buffer)) - - return l:exe . ' --stdio' -endfunction - function! ale_linters#puppet#languageserver#GetProjectRoot(buffer) abort " Note: The metadata.json file is recommended for Puppet 4+ modules, but " there's no requirement to have it, so fall back to the other possible " Puppet module directories let l:root_path = ale#path#FindNearestFile(a:buffer, 'metadata.json') + if !empty(l:root_path) return fnamemodify(l:root_path, ':h') endif @@ -27,6 +18,7 @@ function! ale_linters#puppet#languageserver#GetProjectRoot(buffer) abort \ 'templates', \] let l:root_path = ale#path#FindNearestDirectory(a:buffer, l:test_path) + if !empty(l:root_path) return fnamemodify(l:root_path, ':h:h') endif @@ -38,8 +30,8 @@ endfunction call ale#linter#Define('puppet', { \ 'name': 'languageserver', \ 'lsp': 'stdio', -\ 'executable_callback': 'ale_linters#puppet#languageserver#GetExecutable', -\ 'command_callback': 'ale_linters#puppet#languageserver#GetCommand', +\ 'executable_callback': ale#VarFunc('puppet_languageserver_executable'), +\ 'command': '%e --stdio', \ 'language': 'puppet', \ 'project_root_callback': 'ale_linters#puppet#languageserver#GetProjectRoot', \}) diff --git a/ale_linters/puppet/puppet.vim b/ale_linters/puppet/puppet.vim index 4ca0dd55..0e37bdbd 100644 --- a/ale_linters/puppet/puppet.vim +++ b/ale_linters/puppet/puppet.vim @@ -1,11 +1,13 @@ " Author: Alexander Olofsson <alexander.olofsson@liu.se> +call ale#Set('puppet_puppet_executable', 'puppet') +call ale#Set('puppet_puppet_options', '') + function! ale_linters#puppet#puppet#Handle(buffer, lines) abort " Matches patterns like the following: " Error: Could not parse for environment production: Syntax error at ':' at /root/puppetcode/modules/nginx/manifests/init.pp:43:12 " Error: Could not parse for environment production: Syntax error at '='; expected '}' at /root/puppetcode/modules/pancakes/manifests/init.pp:5" " Error: Could not parse for environment production: Syntax error at 'parameter1' (file: /tmp/modules/mariadb/manifests/slave.pp, line: 4, column: 5) - let l:pattern = '^Error: .*: \(.\+\) \((file:\|at\) .\+\.pp\(, line: \|:\)\(\d\+\)\(, column: \|:\)\=\(\d*\)' let l:output = [] @@ -20,10 +22,16 @@ function! ale_linters#puppet#puppet#Handle(buffer, lines) abort return l:output endfunction +function! ale_linters#puppet#puppet#GetCommand(buffer) abort + return '%e parser validate --color=false ' + \ . ale#Pad(ale#Var(a:buffer, 'puppet_puppet_options')) + \ . ' %t' +endfunction + call ale#linter#Define('puppet', { \ 'name': 'puppet', -\ 'executable': 'puppet', +\ 'executable_callback': ale#VarFunc('puppet_puppet_executable'), \ 'output_stream': 'stderr', -\ 'command': 'puppet parser validate --color=false %t', +\ 'command_callback': 'ale_linters#puppet#puppet#GetCommand', \ 'callback': 'ale_linters#puppet#puppet#Handle', \}) diff --git a/ale_linters/puppet/puppetlint.vim b/ale_linters/puppet/puppetlint.vim index 13da511b..c9c16f5e 100644 --- a/ale_linters/puppet/puppetlint.vim +++ b/ale_linters/puppet/puppetlint.vim @@ -1,26 +1,18 @@ " Author: Alexander Olofsson <alexander.olofsson@liu.se>, Robert Flechtner <flechtner@chemmedia.de> " Description: puppet-lint for puppet files -let g:ale_puppet_puppetlint_executable = -\ get(g:, 'ale_puppet_puppetlint_executable', 'puppet-lint') - -let g:ale_puppet_puppetlint_options = -\ get(g:, 'ale_puppet_puppetlint_options', '--no-autoloader_layout-check') - -function! ale_linters#puppet#puppetlint#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'puppet_puppetlint_executable') -endfunction +call ale#Set('puppet_puppetlint_executable', 'puppet-lint') +call ale#Set('puppet_puppetlint_options', '--no-autoloader_layout-check') function! ale_linters#puppet#puppetlint#GetCommand(buffer) abort - return ale_linters#puppet#puppetlint#GetExecutable(a:buffer) - \ . ' ' . ale#Var(a:buffer, 'puppet_puppetlint_options') + return '%e' . ale#Pad(ale#Var(a:buffer, 'puppet_puppetlint_options')) \ . ' --log-format "-:%{line}:%{column}: %{kind}: [%{check}] %{message}"' \ . ' %t' endfunction call ale#linter#Define('puppet', { \ 'name': 'puppetlint', -\ 'executable_callback': 'ale_linters#puppet#puppetlint#GetExecutable', +\ 'executable_callback': ale#VarFunc('puppet_puppetlint_executable'), \ 'command_callback': 'ale_linters#puppet#puppetlint#GetCommand', \ 'callback': 'ale#handlers#gcc#HandleGCCFormat', \}) diff --git a/ale_linters/pyrex/cython.vim b/ale_linters/pyrex/cython.vim index 9b6b39d7..d260698c 100644 --- a/ale_linters/pyrex/cython.vim +++ b/ale_linters/pyrex/cython.vim @@ -5,16 +5,11 @@ call ale#Set('pyrex_cython_executable', 'cython') call ale#Set('pyrex_cython_options', '--warning-extra') -function! ale_linters#pyrex#cython#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'pyrex_cython_executable') -endfunction - function! ale_linters#pyrex#cython#GetCommand(buffer) abort let l:local_dir = ale#Escape(fnamemodify(bufname(a:buffer), ':p:h')) - return ale#Escape(ale_linters#pyrex#cython#GetExecutable(a:buffer)) - \ . ' --working ' . l:local_dir . ' --include-dir ' . l:local_dir - \ . ' ' . ale#Var(a:buffer, 'pyrex_cython_options') + return '%e --working ' . l:local_dir . ' --include-dir ' . l:local_dir + \ . ale#Pad(ale#Var(a:buffer, 'pyrex_cython_options')) \ . ' --output-file ' . g:ale#util#nul_file . ' %t' endfunction @@ -37,7 +32,7 @@ endfunction call ale#linter#Define('pyrex', { \ 'name': 'cython', \ 'output_stream': 'stderr', -\ 'executable_callback': 'ale_linters#pyrex#cython#GetExecutable', +\ 'executable_callback': ale#VarFunc('pyrex_cython_executable'), \ 'command_callback': 'ale_linters#pyrex#cython#GetCommand', \ 'callback': 'ale_linters#pyrex#cython#Handle', \}) diff --git a/ale_linters/python/flake8.vim b/ale_linters/python/flake8.vim index 358f51a4..14b67d77 100644 --- a/ale_linters/python/flake8.vim +++ b/ale_linters/python/flake8.vim @@ -5,12 +5,18 @@ call ale#Set('python_flake8_executable', 'flake8') call ale#Set('python_flake8_options', '') call ale#Set('python_flake8_use_global', get(g:, 'ale_use_global_executables', 0)) call ale#Set('python_flake8_change_directory', 1) +call ale#Set('python_flake8_auto_pipenv', 0) function! s:UsingModule(buffer) abort return ale#Var(a:buffer, 'python_flake8_options') =~# ' *-m flake8' endfunction function! ale_linters#python#flake8#GetExecutable(buffer) abort + if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_flake8_auto_pipenv')) + \ && ale#python#PipenvPresent(a:buffer) + return 'pipenv' + endif + if !s:UsingModule(a:buffer) return ale#python#FindExecutable(a:buffer, 'python_flake8', ['flake8']) endif @@ -104,6 +110,7 @@ function! ale_linters#python#flake8#Handle(buffer, lines) abort let l:item = { \ 'lnum': l:match[1] + 0, \ 'col': l:match[2] + 0, + \ 'vcol': 1, \ 'text': l:match[4], \ 'code': l:code, \ 'type': 'W', diff --git a/ale_linters/python/mypy.vim b/ale_linters/python/mypy.vim index b38ccdeb..0c90a3c7 100644 --- a/ale_linters/python/mypy.vim +++ b/ale_linters/python/mypy.vim @@ -5,8 +5,14 @@ call ale#Set('python_mypy_executable', 'mypy') call ale#Set('python_mypy_ignore_invalid_syntax', 0) call ale#Set('python_mypy_options', '') call ale#Set('python_mypy_use_global', get(g:, 'ale_use_global_executables', 0)) +call ale#Set('python_mypy_auto_pipenv', 0) function! ale_linters#python#mypy#GetExecutable(buffer) abort + if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_mypy_auto_pipenv')) + \ && ale#python#PipenvPresent(a:buffer) + return 'pipenv' + endif + return ale#python#FindExecutable(a:buffer, 'python_mypy', ['mypy']) endfunction diff --git a/ale_linters/python/prospector.vim b/ale_linters/python/prospector.vim index fff37147..b01cec87 100644 --- a/ale_linters/python/prospector.vim +++ b/ale_linters/python/prospector.vim @@ -1,6 +1,8 @@ " Author: chocoelho <carlospecter@gmail.com> " Description: prospector linter python files +call ale#Set('python_prospector_auto_pipenv', 0) + let g:ale_python_prospector_executable = \ get(g:, 'ale_python_prospector_executable', 'prospector') @@ -10,6 +12,11 @@ let g:ale_python_prospector_options = let g:ale_python_prospector_use_global = get(g:, 'ale_python_prospector_use_global', get(g:, 'ale_use_global_executables', 0)) function! ale_linters#python#prospector#GetExecutable(buffer) abort + if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_prospector_auto_pipenv')) + \ && ale#python#PipenvPresent(a:buffer) + return 'pipenv' + endif + return ale#python#FindExecutable(a:buffer, 'python_prospector', ['prospector']) endfunction diff --git a/ale_linters/python/pycodestyle.vim b/ale_linters/python/pycodestyle.vim index de96363f..f0269585 100644 --- a/ale_linters/python/pycodestyle.vim +++ b/ale_linters/python/pycodestyle.vim @@ -4,8 +4,14 @@ call ale#Set('python_pycodestyle_executable', 'pycodestyle') call ale#Set('python_pycodestyle_options', '') call ale#Set('python_pycodestyle_use_global', get(g:, 'ale_use_global_executables', 0)) +call ale#Set('python_pycodestyle_auto_pipenv', 0) function! ale_linters#python#pycodestyle#GetExecutable(buffer) abort + if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_pycodestyle_auto_pipenv')) + \ && ale#python#PipenvPresent(a:buffer) + return 'pipenv' + endif + return ale#python#FindExecutable(a:buffer, 'python_pycodestyle', ['pycodestyle']) endfunction diff --git a/ale_linters/python/pyflakes.vim b/ale_linters/python/pyflakes.vim index 86ff8773..091408d5 100644 --- a/ale_linters/python/pyflakes.vim +++ b/ale_linters/python/pyflakes.vim @@ -3,8 +3,14 @@ call ale#Set('python_pyflakes_executable', 'pyflakes') call ale#Set('python_pyflakes_use_global', get(g:, 'ale_use_global_executables', 0)) +call ale#Set('python_pyflakes_auto_pipenv', 0) function! ale_linters#python#pyflakes#GetExecutable(buffer) abort + if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_pyflakes_auto_pipenv')) + \ && ale#python#PipenvPresent(a:buffer) + return 'pipenv' + endif + return ale#python#FindExecutable(a:buffer, 'python_pyflakes', ['pyflakes']) endfunction diff --git a/ale_linters/python/pylint.vim b/ale_linters/python/pylint.vim index 9239f835..01c3cb37 100644 --- a/ale_linters/python/pylint.vim +++ b/ale_linters/python/pylint.vim @@ -5,8 +5,14 @@ call ale#Set('python_pylint_executable', 'pylint') call ale#Set('python_pylint_options', '') call ale#Set('python_pylint_use_global', get(g:, 'ale_use_global_executables', 0)) call ale#Set('python_pylint_change_directory', 1) +call ale#Set('python_pylint_auto_pipenv', 0) function! ale_linters#python#pylint#GetExecutable(buffer) abort + if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_pylint_auto_pipenv')) + \ && ale#python#PipenvPresent(a:buffer) + return 'pipenv' + endif + return ale#python#FindExecutable(a:buffer, 'python_pylint', ['pylint']) endfunction diff --git a/ale_linters/python/pyls.vim b/ale_linters/python/pyls.vim index ae71f022..83fe8066 100644 --- a/ale_linters/python/pyls.vim +++ b/ale_linters/python/pyls.vim @@ -3,8 +3,14 @@ call ale#Set('python_pyls_executable', 'pyls') call ale#Set('python_pyls_use_global', get(g:, 'ale_use_global_executables', 0)) +call ale#Set('python_pyls_auto_pipenv', 0) function! ale_linters#python#pyls#GetExecutable(buffer) abort + if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_pyls_auto_pipenv')) + \ && ale#python#PipenvPresent(a:buffer) + return 'pipenv' + endif + return ale#python#FindExecutable(a:buffer, 'python_pyls', ['pyls']) endfunction diff --git a/ale_linters/python/pyre.vim b/ale_linters/python/pyre.vim index 5efef409..adc185f2 100644 --- a/ale_linters/python/pyre.vim +++ b/ale_linters/python/pyre.vim @@ -3,8 +3,14 @@ call ale#Set('python_pyre_executable', 'pyre') call ale#Set('python_pyre_use_global', get(g:, 'ale_use_global_executables', 0)) +call ale#Set('python_pyre_auto_pipenv', 0) function! ale_linters#python#pyre#GetExecutable(buffer) abort + if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_pyre_auto_pipenv')) + \ && ale#python#PipenvPresent(a:buffer) + return 'pipenv' + endif + return ale#python#FindExecutable(a:buffer, 'python_pyre', ['pyre']) endfunction diff --git a/ale_linters/python/vulture.vim b/ale_linters/python/vulture.vim new file mode 100644 index 00000000..80828013 --- /dev/null +++ b/ale_linters/python/vulture.vim @@ -0,0 +1,85 @@ +" Author: Yauheni Kirylau <actionless.loveless@gmail.com> +" Description: vulture linting for python files + +call ale#Set('python_vulture_executable', 'vulture') +call ale#Set('python_vulture_options', '') +call ale#Set('python_vulture_use_global', get(g:, 'ale_use_global_executables', 0)) +call ale#Set('python_vulture_change_directory', 1) + + +" The directory to change to before running vulture +function! s:GetDir(buffer) abort + let l:project_root = ale#python#FindProjectRoot(a:buffer) + + return !empty(l:project_root) + \ ? l:project_root + \ : expand('#' . a:buffer . ':p:h') +endfunction + + +function! ale_linters#python#vulture#GetExecutable(buffer) abort + return ale#python#FindExecutable(a:buffer, 'python_vulture', ['vulture']) +endfunction + + +function! ale_linters#python#vulture#GetCommand(buffer) abort + let l:change_dir = ale#Var(a:buffer, 'python_vulture_change_directory') + \ ? ale#path#CdString(s:GetDir(a:buffer)) + \ : '' + + let l:executable = ale_linters#python#vulture#GetExecutable(a:buffer) + + let l:exec_args = l:executable =~? 'pipenv$' + \ ? ' run vulture' + \ : '' + + let l:lint_dest = ale#Var(a:buffer, 'python_vulture_change_directory') + \ ? ' .' + \ : ' %s' + + return l:change_dir + \ . ale#Escape(l:executable) . l:exec_args + \ . ' ' + \ . ale#Var(a:buffer, 'python_vulture_options') + \ . l:lint_dest +endfunction + + +function! ale_linters#python#vulture#Handle(buffer, lines) abort + for l:line in a:lines[:10] + if match(l:line, '^Traceback') >= 0 + return [{ + \ 'lnum': 1, + \ 'text': 'An exception was thrown. See :ALEDetail', + \ 'detail': join(a:lines, "\n"), + \}] + endif + endfor + + " Matches patterns line the following: + let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+): (.*)$' + let l:output = [] + let l:dir = s:GetDir(a:buffer) + + for l:match in ale#util#GetMatches(a:lines, l:pattern) + let l:abspath = ale#path#GetAbsPath(l:dir, l:match[1]) + let l:item = { + \ 'filename': l:abspath, + \ 'lnum': l:match[2] + 0, + \ 'text': l:match[3], + \ 'type': 'W', + \} + call add(l:output, l:item) + endfor + + return l:output +endfunction + + +call ale#linter#Define('python', { +\ 'name': 'vulture', +\ 'executable_callback': 'ale_linters#python#vulture#GetExecutable', +\ 'command_callback': 'ale_linters#python#vulture#GetCommand', +\ 'callback': 'ale_linters#python#vulture#Handle', +\ 'lint_file': 1, +\}) diff --git a/ale_linters/qml/qmlfmt.vim b/ale_linters/qml/qmlfmt.vim index 85b131fd..12f3e97b 100644 --- a/ale_linters/qml/qmlfmt.vim +++ b/ale_linters/qml/qmlfmt.vim @@ -1,40 +1,25 @@ " Author: pylipp (www.github.com/pylipp) " Description: qmlfmt for QML files -let g:ale_qml_qmlfmt_executable = get(g:, 'ale_qml_qmlfmt_executable', 'qmlfmt') - -function! ale_linters#qml#qmlfmt#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'qml_qmlfmt_executable') -endfunction - -function! ale_linters#qml#qmlfmt#GetCommand(buffer) abort - return ale#Escape(ale_linters#qml#qmlfmt#GetExecutable(a:buffer)) - \ . ' -e' -endfunction +call ale#Set('qml_qmlfmt_executable', 'qmlfmt') " Find lines like " Error:11:1: Expected token `}' function! ale_linters#qml#qmlfmt#Handle(buffer, lines) abort let l:pattern = '\v^(Error|Warning):(\d+):(\d+): (.+)$' - let l:output = [] - - for l:match in ale#util#GetMatches(a:lines, l:pattern) - let l:item = { - \ 'lnum': l:match[2] + 0, - \ 'col': l:match[3] + 0, - \ 'text': l:match[4], - \ 'type': l:match[1] is# 'Warning' ? 'W' : 'E', - \} - call add(l:output, l:item) - endfor - return l:output + return map(ale#util#GetMatches(a:lines, l:pattern), "{ + \ 'lnum': v:val[2] + 0, + \ 'col': v:val[3] + 0, + \ 'text': v:val[4], + \ 'type': v:val[1] is# 'Warning' ? 'W' : 'E', + \}") endfunction call ale#linter#Define('qml', { \ 'name': 'qmlfmt', \ 'output_stream': 'stderr', -\ 'executable_callback': 'ale_linters#qml#qmlfmt#GetExecutable', -\ 'command_callback': 'ale_linters#qml#qmlfmt#GetCommand', +\ 'executable_callback': ale#VarFunc('qml_qmlfmt_executable'), +\ 'command': '%e -e', \ 'callback': 'ale_linters#qml#qmlfmt#Handle', \}) diff --git a/ale_linters/rst/rstcheck.vim b/ale_linters/rst/rstcheck.vim index b660627f..8504738b 100644 --- a/ale_linters/rst/rstcheck.vim +++ b/ale_linters/rst/rstcheck.vim @@ -8,6 +8,7 @@ function! ale_linters#rst#rstcheck#Handle(buffer, lines) abort let l:pattern = '\v^(.+):(\d*): \(([a-zA-Z]*)/\d*\) (.+)$' let l:dir = expand('#' . a:buffer . ':p:h') let l:output = [] + for l:match in ale#util#GetMatches(a:lines, l:pattern) call add(l:output, { \ 'filename': ale#path#GetAbsPath(l:dir, l:match[1]), diff --git a/ale_linters/ruby/brakeman.vim b/ale_linters/ruby/brakeman.vim index 85cfc184..122e0b5b 100644 --- a/ale_linters/ruby/brakeman.vim +++ b/ale_linters/ruby/brakeman.vim @@ -1,8 +1,9 @@ " Author: Eddie Lebow https://github.com/elebow " Description: Brakeman, a static analyzer for Rails security -let g:ale_ruby_brakeman_options = -\ get(g:, 'ale_ruby_brakeman_options', '') +call ale#Set('ruby_brakeman_options', '') +call ale#Set('ruby_brakeman_executable', 'brakeman') +call ale#Set('ruby_brakeman_options', '') function! ale_linters#ruby#brakeman#Handle(buffer, lines) abort let l:output = [] @@ -33,14 +34,17 @@ function! ale_linters#ruby#brakeman#GetCommand(buffer) abort return '' endif - return 'brakeman -f json -q ' + let l:executable = ale#Var(a:buffer, 'ruby_brakeman_executable') + + return ale#handlers#ruby#EscapeExecutable(l:executable, 'brakeman') + \ . ' -f json -q ' \ . ale#Var(a:buffer, 'ruby_brakeman_options') \ . ' -p ' . ale#Escape(l:rails_root) endfunction call ale#linter#Define('ruby', { \ 'name': 'brakeman', -\ 'executable': 'brakeman', +\ 'executable_callback': ale#VarFunc('ruby_brakeman_executable'), \ 'command_callback': 'ale_linters#ruby#brakeman#GetCommand', \ 'callback': 'ale_linters#ruby#brakeman#Handle', \ 'lint_file': 1, diff --git a/ale_linters/ruby/rails_best_practices.vim b/ale_linters/ruby/rails_best_practices.vim index 4ba1f3fe..20cadca8 100644 --- a/ale_linters/ruby/rails_best_practices.vim +++ b/ale_linters/ruby/rails_best_practices.vim @@ -22,26 +22,18 @@ function! ale_linters#ruby#rails_best_practices#Handle(buffer, lines) abort return l:output endfunction -function! ale_linters#ruby#rails_best_practices#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'ruby_rails_best_practices_executable') -endfunction - function! ale_linters#ruby#rails_best_practices#GetCommand(buffer) abort - let l:executable = ale_linters#ruby#rails_best_practices#GetExecutable(a:buffer) - let l:exec_args = l:executable =~? 'bundle$' - \ ? ' exec rails_best_practices' - \ : '' - let l:rails_root = ale#ruby#FindRailsRoot(a:buffer) if l:rails_root is? '' return '' endif + let l:executable = ale#Var(a:buffer, 'ruby_rails_best_practices_executable') let l:output_file = ale#Has('win32') ? '%t ' : '/dev/stdout ' let l:cat_file = ale#Has('win32') ? '; type %t' : '' - return ale#Escape(l:executable) . l:exec_args + return ale#handlers#ruby#EscapeExecutable(l:executable, 'rails_best_practices') \ . ' --silent -f json --output-file ' . l:output_file \ . ale#Var(a:buffer, 'ruby_rails_best_practices_options') \ . ale#Escape(l:rails_root) @@ -50,7 +42,7 @@ endfunction call ale#linter#Define('ruby', { \ 'name': 'rails_best_practices', -\ 'executable_callback': 'ale_linters#ruby#rails_best_practices#GetExecutable', +\ 'executable_callback': ale#VarFunc('ruby_rails_best_practices_executable'), \ 'command_callback': 'ale_linters#ruby#rails_best_practices#GetCommand', \ 'callback': 'ale_linters#ruby#rails_best_practices#Handle', \ 'lint_file': 1, diff --git a/ale_linters/ruby/reek.vim b/ale_linters/ruby/reek.vim index aa5d8d70..53363d31 100644 --- a/ale_linters/ruby/reek.vim +++ b/ale_linters/ruby/reek.vim @@ -3,6 +3,8 @@ call ale#Set('ruby_reek_show_context', 0) call ale#Set('ruby_reek_show_wiki_link', 0) +call ale#Set('ruby_reek_options', '') +call ale#Set('ruby_reek_executable', 'reek') function! ale_linters#ruby#reek#VersionCheck(buffer) abort " If we have previously stored the version number in a cache, then @@ -12,18 +14,23 @@ function! ale_linters#ruby#reek#VersionCheck(buffer) abort return '' endif - return 'reek --version' + let l:executable = ale#Var(a:buffer, 'ruby_reek_executable') + + return ale#handlers#ruby#EscapeExecutable(l:executable, 'reek') + \ . ' --version' endfunction function! ale_linters#ruby#reek#GetCommand(buffer, version_output) abort let l:version = ale#semver#GetVersion('reek', a:version_output) + let l:executable = ale#Var(a:buffer, 'ruby_reek_executable') " Tell reek what the filename is if the version of reek is new enough. let l:display_name_args = ale#semver#GTE(l:version, [5, 0, 0]) \ ? ' --stdin-filename %s' \ : '' - return 'reek -f json --no-progress --no-color' + return ale#handlers#ruby#EscapeExecutable(l:executable, 'reek') + \ . ' -f json --no-progress --no-color --force-exclusion' \ . l:display_name_args endfunction @@ -62,7 +69,7 @@ endfunction call ale#linter#Define('ruby', { \ 'name': 'reek', -\ 'executable': 'reek', +\ 'executable_callback': ale#VarFunc('ruby_reek_executable'), \ 'command_chain': [ \ {'callback': 'ale_linters#ruby#reek#VersionCheck'}, \ {'callback': 'ale_linters#ruby#reek#GetCommand'}, diff --git a/ale_linters/ruby/rubocop.vim b/ale_linters/ruby/rubocop.vim index 777f457a..45218394 100644 --- a/ale_linters/ruby/rubocop.vim +++ b/ale_linters/ruby/rubocop.vim @@ -1,13 +1,13 @@ " Author: ynonp - https://github.com/ynonp, Eddie Lebow https://github.com/elebow " Description: RuboCop, a code style analyzer for Ruby files +call ale#Set('ruby_rubocop_executable', 'rubocop') +call ale#Set('ruby_rubocop_options', '') + function! ale_linters#ruby#rubocop#GetCommand(buffer) abort - let l:executable = ale#handlers#rubocop#GetExecutable(a:buffer) - let l:exec_args = l:executable =~? 'bundle$' - \ ? ' exec rubocop' - \ : '' + let l:executable = ale#Var(a:buffer, 'ruby_rubocop_executable') - return ale#Escape(l:executable) . l:exec_args + return ale#handlers#ruby#EscapeExecutable(l:executable, 'rubocop') \ . ' --format json --force-exclusion ' \ . ale#Var(a:buffer, 'ruby_rubocop_options') \ . ' --stdin ' . ale#Escape(expand('#' . a:buffer . ':p')) @@ -55,7 +55,7 @@ endfunction call ale#linter#Define('ruby', { \ 'name': 'rubocop', -\ 'executable_callback': 'ale#handlers#rubocop#GetExecutable', +\ 'executable_callback': ale#VarFunc('ruby_rubocop_executable'), \ 'command_callback': 'ale_linters#ruby#rubocop#GetCommand', \ 'callback': 'ale_linters#ruby#rubocop#Handle', \}) diff --git a/ale_linters/ruby/ruby.vim b/ale_linters/ruby/ruby.vim index 1aa88851..2bc4ec4b 100644 --- a/ale_linters/ruby/ruby.vim +++ b/ale_linters/ruby/ruby.vim @@ -3,20 +3,10 @@ call ale#Set('ruby_ruby_executable', 'ruby') -function! ale_linters#ruby#ruby#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'ruby_ruby_executable') -endfunction - -function! ale_linters#ruby#ruby#GetCommand(buffer) abort - let l:executable = ale_linters#ruby#ruby#GetExecutable(a:buffer) - - return ale#Escape(l:executable) . ' -w -c -T1 %t' -endfunction - call ale#linter#Define('ruby', { \ 'name': 'ruby', -\ 'executable_callback': 'ale_linters#ruby#ruby#GetExecutable', -\ 'command_callback': 'ale_linters#ruby#ruby#GetCommand', +\ 'executable_callback': ale#VarFunc('ruby_ruby_executable'), +\ 'command': '%e -w -c -T1 %t', \ 'output_stream': 'stderr', \ 'callback': 'ale#handlers#ruby#HandleSyntaxErrors', \}) diff --git a/ale_linters/ruby/solargraph.vim b/ale_linters/ruby/solargraph.vim new file mode 100644 index 00000000..5ff0a759 --- /dev/null +++ b/ale_linters/ruby/solargraph.vim @@ -0,0 +1,22 @@ +" Author: Horacio Sanson - https://github.com/hsanson +" Description: Solargraph Language Server https://solargraph.org/ +" +" Author: Devon Meunier <devon.meunier@gmail.com> +" Description: updated to use stdio + +call ale#Set('ruby_solargraph_executable', 'solargraph') +call ale#Set('ruby_solargraph_options', {}) + +function! ale_linters#ruby#solargraph#GetCommand(buffer) abort + return '%e' . ale#Pad('stdio') +endfunction + +call ale#linter#Define('ruby', { +\ 'name': 'solargraph', +\ 'lsp': 'stdio', +\ 'language': 'ruby', +\ 'executable_callback': ale#VarFunc('ruby_solargraph_executable'), +\ 'command_callback': 'ale_linters#ruby#solargraph#GetCommand', +\ 'project_root_callback': 'ale#ruby#FindProjectRoot', +\ 'initialization_options_callback': ale#VarFunc('ruby_solargraph_options'), +\}) diff --git a/ale_linters/rust/cargo.vim b/ale_linters/rust/cargo.vim index e6c3870a..cf6187f8 100644 --- a/ale_linters/rust/cargo.vim +++ b/ale_linters/rust/cargo.vim @@ -9,6 +9,8 @@ call ale#Set('rust_cargo_check_tests', 0) call ale#Set('rust_cargo_avoid_whole_workspace', 1) call ale#Set('rust_cargo_default_feature_behavior', 'default') call ale#Set('rust_cargo_include_features', '') +call ale#Set('rust_cargo_use_clippy', 0) +call ale#Set('rust_cargo_clippy_options', '') function! ale_linters#rust#cargo#GetCargoExecutable(bufnr) abort if ale#path#FindNearestFile(a:bufnr, 'Cargo.toml') isnot# '' @@ -42,6 +44,7 @@ function! ale_linters#rust#cargo#GetCommand(buffer, version_output) abort \ && ale#semver#GTE(l:version, [0, 22, 0]) let l:include_features = ale#Var(a:buffer, 'rust_cargo_include_features') + if !empty(l:include_features) let l:include_features = ' --features ' . ale#Escape(l:include_features) endif @@ -59,6 +62,7 @@ function! ale_linters#rust#cargo#GetCommand(buffer, version_output) abort endif let l:default_feature_behavior = ale#Var(a:buffer, 'rust_cargo_default_feature_behavior') + if l:default_feature_behavior is# 'all' let l:include_features = '' let l:default_feature = ' --all-features' @@ -68,14 +72,23 @@ function! ale_linters#rust#cargo#GetCommand(buffer, version_output) abort let l:default_feature = '' endif + let l:subcommand = l:use_check ? 'check' : 'build' + let l:clippy_options = '' + + if ale#Var(a:buffer, 'rust_cargo_use_clippy') + let l:subcommand = 'clippy' + let l:clippy_options = ' ' . ale#Var(a:buffer, 'rust_cargo_clippy_options') + endif + return l:nearest_cargo_prefix . 'cargo ' - \ . (l:use_check ? 'check' : 'build') + \ . l:subcommand \ . (l:use_all_targets ? ' --all-targets' : '') \ . (l:use_examples ? ' --examples' : '') \ . (l:use_tests ? ' --tests' : '') \ . ' --frozen --message-format=json -q' \ . l:default_feature \ . l:include_features + \ . l:clippy_options endfunction call ale#linter#Define('rust', { diff --git a/ale_linters/rust/rls.vim b/ale_linters/rust/rls.vim index cd13291d..60dd3667 100644 --- a/ale_linters/rust/rls.vim +++ b/ale_linters/rust/rls.vim @@ -4,19 +4,10 @@ call ale#Set('rust_rls_executable', 'rls') call ale#Set('rust_rls_toolchain', 'nightly') -function! ale_linters#rust#rls#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'rust_rls_executable') -endfunction - function! ale_linters#rust#rls#GetCommand(buffer) abort - let l:executable = ale_linters#rust#rls#GetExecutable(a:buffer) let l:toolchain = ale#Var(a:buffer, 'rust_rls_toolchain') - if empty(l:toolchain) - return ale#Escape(l:executable) - else - return ale#Escape(l:executable) . ' +' . ale#Escape(l:toolchain) - endif + return '%e' . (!empty(l:toolchain) ? ' +' . ale#Escape(l:toolchain) : '') endfunction function! ale_linters#rust#rls#GetProjectRoot(buffer) abort @@ -28,7 +19,7 @@ endfunction call ale#linter#Define('rust', { \ 'name': 'rls', \ 'lsp': 'stdio', -\ 'executable_callback': 'ale_linters#rust#rls#GetExecutable', +\ 'executable_callback': ale#VarFunc('rust_rls_executable'), \ 'command_callback': 'ale_linters#rust#rls#GetCommand', \ 'project_root_callback': 'ale_linters#rust#rls#GetProjectRoot', \}) diff --git a/ale_linters/rust/rustc.vim b/ale_linters/rust/rustc.vim index 3cd401b3..33fb72f4 100644 --- a/ale_linters/rust/rustc.vim +++ b/ale_linters/rust/rustc.vim @@ -1,7 +1,7 @@ " Author: Daniel Schemala <istjanichtzufassen@gmail.com> " Description: rustc for rust files -call ale#Set('rust_rustc_options', '-Z no-trans') +call ale#Set('rust_rustc_options', '-Z no-codegen') function! ale_linters#rust#rustc#RustcCommand(buffer) abort " Try to guess the library search path. If the project is managed by cargo, diff --git a/ale_linters/sass/stylelint.vim b/ale_linters/sass/stylelint.vim index fe941d6a..b6286f18 100644 --- a/ale_linters/sass/stylelint.vim +++ b/ale_linters/sass/stylelint.vim @@ -3,20 +3,11 @@ call ale#Set('sass_stylelint_executable', 'stylelint') call ale#Set('sass_stylelint_use_global', get(g:, 'ale_use_global_executables', 0)) -function! ale_linters#sass#stylelint#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'sass_stylelint', [ - \ 'node_modules/.bin/stylelint', - \]) -endfunction - -function! ale_linters#sass#stylelint#GetCommand(buffer) abort - return ale_linters#sass#stylelint#GetExecutable(a:buffer) - \ . ' --stdin-filename %s' -endfunction - call ale#linter#Define('sass', { \ 'name': 'stylelint', -\ 'executable_callback': 'ale_linters#sass#stylelint#GetExecutable', -\ 'command_callback': 'ale_linters#sass#stylelint#GetCommand', +\ 'executable_callback': ale#node#FindExecutableFunc('sass_stylelint', [ +\ 'node_modules/.bin/stylelint', +\ ]), +\ 'command': '%e --stdin-filename %s', \ 'callback': 'ale#handlers#css#HandleStyleLintFormat', \}) diff --git a/ale_linters/scala/fsc.vim b/ale_linters/scala/fsc.vim index 17b26f0b..fbdce20e 100644 --- a/ale_linters/scala/fsc.vim +++ b/ale_linters/scala/fsc.vim @@ -1,29 +1,14 @@ " Author: Nils Leuzinger - https://github.com/PawkyPenguin " Description: Basic scala support using fsc -" -function! ale_linters#scala#fsc#GetExecutable(buffer) abort - if index(split(getbufvar(a:buffer, '&filetype'), '\.'), 'sbt') >= 0 - " Don't check sbt files - return '' - endif - return 'fsc' -endfunction - -function! ale_linters#scala#fsc#GetCommand(buffer) abort - let l:executable = ale_linters#scala#fsc#GetExecutable(a:buffer) - - if empty(l:executable) - return '' - endif - - return ale#Escape(l:executable) . ' -Ystop-after:parser %t' +function! s:IsSbt(buffer) abort + return index(split(getbufvar(a:buffer, '&filetype'), '\.'), 'sbt') >= 0 endfunction call ale#linter#Define('scala', { \ 'name': 'fsc', -\ 'executable_callback': 'ale_linters#scala#fsc#GetExecutable', -\ 'command_callback': 'ale_linters#scala#fsc#GetCommand', +\ 'executable_callback': {buf -> s:IsSbt(buf) ? '' : 'fsc'}, +\ 'command': '%e -Ystop-after:parser %t', \ 'callback': 'ale#handlers#scala#HandleScalacLintFormat', \ 'output_stream': 'stderr', \}) diff --git a/ale_linters/scala/sbtserver.vim b/ale_linters/scala/sbtserver.vim new file mode 100644 index 00000000..694241d7 --- /dev/null +++ b/ale_linters/scala/sbtserver.vim @@ -0,0 +1,31 @@ +" Author: ophirr33 <coghlan.ty@gmail.com> +" Description: TCP lsp client for sbt Server + +call ale#Set('scala_sbtserver_address', '127.0.0.1:4273') +call ale#Set('scala_sbtserver_project_root', '') + +function! ale_linters#scala#sbtserver#GetProjectRoot(buffer) abort + let l:project_root = ale#Var(a:buffer, 'scala_sbtserver_project_root') + + if l:project_root is? '' + let l:project_root = ale#path#FindNearestFile(a:buffer, 'build.sbt') + + return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' + endif + + return l:project_root +endfunction + +function! ale_linters#scala#sbtserver#GetAddress(buffer) abort + let l:address = ale#Var(a:buffer, 'scala_sbtserver_address') + + return l:address +endfunction + +call ale#linter#Define('scala', { +\ 'name': 'sbtserver', +\ 'lsp': 'socket', +\ 'address_callback': 'ale_linters#scala#sbtserver#GetAddress', +\ 'language': 'scala', +\ 'project_root_callback': 'ale_linters#scala#sbtserver#GetProjectRoot', +\}) diff --git a/ale_linters/scala/scalac.vim b/ale_linters/scala/scalac.vim index 551284af..ba105927 100644 --- a/ale_linters/scala/scalac.vim +++ b/ale_linters/scala/scalac.vim @@ -2,29 +2,14 @@ " w0rp <devw0rp@gmail.com> " Description: Basic scala support using scalac -function! ale_linters#scala#scalac#GetExecutable(buffer) abort - if index(split(getbufvar(a:buffer, '&filetype'), '\.'), 'sbt') >= 0 - " Don't check sbt files - return '' - endif - - return 'scalac' -endfunction - -function! ale_linters#scala#scalac#GetCommand(buffer) abort - let l:executable = ale_linters#scala#scalac#GetExecutable(a:buffer) - - if empty(l:executable) - return '' - endif - - return ale#Escape(l:executable) . ' -Ystop-after:parser %t' +function! s:IsSbt(buffer) abort + return index(split(getbufvar(a:buffer, '&filetype'), '\.'), 'sbt') >= 0 endfunction call ale#linter#Define('scala', { \ 'name': 'scalac', -\ 'executable_callback': 'ale_linters#scala#scalac#GetExecutable', -\ 'command_callback': 'ale_linters#scala#scalac#GetCommand', +\ 'executable_callback': {buf -> s:IsSbt(buf) ? '' : 'scalac'}, +\ 'command': '%e -Ystop-before:jvm %t', \ 'callback': 'ale#handlers#scala#HandleScalacLintFormat', \ 'output_stream': 'stderr', \}) diff --git a/ale_linters/scala/scalastyle.vim b/ale_linters/scala/scalastyle.vim index 3232d70b..42228cf6 100644 --- a/ale_linters/scala/scalastyle.vim +++ b/ale_linters/scala/scalastyle.vim @@ -53,12 +53,14 @@ function! ale_linters#scala#scalastyle#GetCommand(buffer) abort \ 'scalastyle_config.xml', \ 'scalastyle-config.xml' \] + for l:config in l:potential_configs let l:scalastyle_config = ale#path#ResolveLocalPath( \ a:buffer, \ l:config, \ '' \) + if !empty(l:scalastyle_config) break endif diff --git a/ale_linters/scss/stylelint.vim b/ale_linters/scss/stylelint.vim index 6bfdd09a..2bffa8e1 100644 --- a/ale_linters/scss/stylelint.vim +++ b/ale_linters/scss/stylelint.vim @@ -1,22 +1,19 @@ " Author: diartyz <diartyz@gmail.com> call ale#Set('scss_stylelint_executable', 'stylelint') +call ale#Set('scss_stylelint_options', '') call ale#Set('scss_stylelint_use_global', get(g:, 'ale_use_global_executables', 0)) -function! ale_linters#scss#stylelint#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'scss_stylelint', [ - \ 'node_modules/.bin/stylelint', - \]) -endfunction - function! ale_linters#scss#stylelint#GetCommand(buffer) abort - return ale_linters#scss#stylelint#GetExecutable(a:buffer) + return '%e ' . ale#Pad(ale#Var(a:buffer, 'scss_stylelint_options')) \ . ' --stdin-filename %s' endfunction call ale#linter#Define('scss', { \ 'name': 'stylelint', -\ 'executable_callback': 'ale_linters#scss#stylelint#GetExecutable', +\ 'executable_callback': ale#node#FindExecutableFunc('scss_stylelint', [ +\ 'node_modules/.bin/stylelint', +\ ]), \ 'command_callback': 'ale_linters#scss#stylelint#GetCommand', \ 'callback': 'ale#handlers#css#HandleStyleLintFormat', \}) diff --git a/ale_linters/sh/shellcheck.vim b/ale_linters/sh/shellcheck.vim index 27c74531..0f68e62c 100644 --- a/ale_linters/sh/shellcheck.vim +++ b/ale_linters/sh/shellcheck.vim @@ -6,14 +6,9 @@ " codes to exclude from shellcheck. For example: " " let g:ale_sh_shellcheck_exclusions = 'SC2002,SC2004' -let g:ale_sh_shellcheck_exclusions = -\ get(g:, 'ale_sh_shellcheck_exclusions', get(g:, 'ale_linters_sh_shellcheck_exclusions', '')) - -let g:ale_sh_shellcheck_executable = -\ get(g:, 'ale_sh_shellcheck_executable', 'shellcheck') - -let g:ale_sh_shellcheck_options = -\ get(g:, 'ale_sh_shellcheck_options', '') +call ale#Set('sh_shellcheck_exclusions', get(g:, 'ale_linters_sh_shellcheck_exclusions', '')) +call ale#Set('sh_shellcheck_executable', 'shellcheck') +call ale#Set('sh_shellcheck_options', '') function! ale_linters#sh#shellcheck#GetExecutable(buffer) abort return ale#Var(a:buffer, 'sh_shellcheck_executable') diff --git a/ale_linters/sml/smlnj_cm.vim b/ale_linters/sml/smlnj_cm.vim index 7a482307..bfa4bc05 100644 --- a/ale_linters/sml/smlnj_cm.vim +++ b/ale_linters/sml/smlnj_cm.vim @@ -3,6 +3,7 @@ function! ale_linters#sml#smlnj_cm#GetCommand(buffer) abort let l:cmfile = ale#handlers#sml#GetCmFile(a:buffer) + return 'sml -m ' . l:cmfile . ' < /dev/null' endfunction diff --git a/ale_linters/solidity/solhint.vim b/ale_linters/solidity/solhint.vim index 519fd49d..8ea33e07 100644 --- a/ale_linters/solidity/solhint.vim +++ b/ale_linters/solidity/solhint.vim @@ -4,7 +4,6 @@ function! ale_linters#solidity#solhint#Handle(buffer, lines) abort " Matches patterns like the following: " /path/to/file/file.sol: line 1, col 10, Error - 'addOne' is defined but never used. (no-unused-vars) - let l:pattern = '\v^[^:]+: line (\d+), col (\d+), (Error|Warning) - (.*) \((.*)\)$' let l:output = [] diff --git a/ale_linters/spec/rpmlint.vim b/ale_linters/spec/rpmlint.vim index f5308af6..486bef1e 100644 --- a/ale_linters/spec/rpmlint.vim +++ b/ale_linters/spec/rpmlint.vim @@ -26,19 +26,12 @@ " And this is always output at the end and should just be ignored: " 0 packages and 1 specfiles checked; 4 errors, 0 warnings. -let g:ale_spec_rpmlint_executable = -\ get(g:, 'ale_spec_rpmlint_executable', 'rpmlint') - -let g:ale_spec_rpmlint_options = -\ get(g:, 'ale_spec_rpmlint_options', '') - -function! ale_linters#spec#rpmlint#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'spec_rpmlint_executable') -endfunction +call ale#Set('spec_rpmlint_executable', 'rpmlint') +call ale#Set('spec_rpmlint_options', '') function! ale_linters#spec#rpmlint#GetCommand(buffer) abort - return ale_linters#spec#rpmlint#GetExecutable(a:buffer) - \ . ' ' . ale#Var(a:buffer, 'spec_rpmlint_options') + return '%e' + \ . ale#Pad(ale#Var(a:buffer, 'spec_rpmlint_options')) \ . ' -o "NetworkEnabled False"' \ . ' -v' \ . ' %t' @@ -79,7 +72,7 @@ endfunction call ale#linter#Define('spec', { \ 'name': 'rpmlint', -\ 'executable_callback': 'ale_linters#spec#rpmlint#GetExecutable', +\ 'executable_callback': ale#VarFunc('spec_rpmlint_executable'), \ 'command_callback': 'ale_linters#spec#rpmlint#GetCommand', \ 'callback': 'ale_linters#spec#rpmlint#Handle', \}) diff --git a/ale_linters/stylus/stylelint.vim b/ale_linters/stylus/stylelint.vim index 1562692a..2256f3c0 100644 --- a/ale_linters/stylus/stylelint.vim +++ b/ale_linters/stylus/stylelint.vim @@ -4,21 +4,17 @@ call ale#Set('stylus_stylelint_executable', 'stylelint') call ale#Set('stylus_stylelint_options', '') call ale#Set('stylus_stylelint_use_global', get(g:, 'ale_use_global_executables', 0)) -function! ale_linters#stylus#stylelint#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'stylus_stylelint', [ - \ 'node_modules/.bin/stylelint', - \]) -endfunction - function! ale_linters#stylus#stylelint#GetCommand(buffer) abort - return ale_linters#stylus#stylelint#GetExecutable(a:buffer) - \ . ' ' . ale#Var(a:buffer, 'stylus_stylelint_options') + return '%e' + \ . ale#Pad(ale#Var(a:buffer, 'stylus_stylelint_options')) \ . ' --stdin-filename %s' endfunction call ale#linter#Define('stylus', { \ 'name': 'stylelint', -\ 'executable_callback': 'ale_linters#stylus#stylelint#GetExecutable', +\ 'executable_callback': ale#node#FindExecutableFunc('stylus_stylelint', [ +\ 'node_modules/.bin/stylelint', +\ ]), \ 'command_callback': 'ale_linters#stylus#stylelint#GetCommand', \ 'callback': 'ale#handlers#css#HandleStyleLintFormat', \}) diff --git a/ale_linters/tcl/nagelfar.vim b/ale_linters/tcl/nagelfar.vim index 13b7a549..05fe581b 100644 --- a/ale_linters/tcl/nagelfar.vim +++ b/ale_linters/tcl/nagelfar.vim @@ -4,16 +4,10 @@ call ale#Set('tcl_nagelfar_executable', 'nagelfar.tcl') call ale#Set('tcl_nagelfar_options', '') -function! ale_linters#tcl#nagelfar#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'tcl_nagelfar_executable') -endfunction - function! ale_linters#tcl#nagelfar#GetCommand(buffer) abort let l:options = ale#Var(a:buffer, 'tcl_nagelfar_options') - return ale#Escape(ale_linters#tcl#nagelfar#GetExecutable(a:buffer)) - \ . (!empty(l:options) ? ' ' . l:options : '') - \ . ' %s' + return '%e' . ale#Pad(l:options) . ' %s' endfunction function! ale_linters#tcl#nagelfar#Handle(buffer, lines) abort @@ -21,7 +15,6 @@ function! ale_linters#tcl#nagelfar#Handle(buffer, lines) abort " Line 5: W Found constant "bepa" which is also a variable. " Line 13: E Wrong number of arguments (3) to "set" " Line 93: N Close brace not aligned with line 90 (4 0) - let l:pattern = '^Line\s\+\([0-9]\+\): \([NEW]\) \(.*\)$' let l:output = [] @@ -39,7 +32,7 @@ endfunction call ale#linter#Define('tcl', { \ 'name': 'nagelfar', \ 'output_stream': 'stdout', -\ 'executable_callback': 'ale_linters#tcl#nagelfar#GetExecutable', +\ 'executable_callback': ale#VarFunc('tcl_nagelfar_executable'), \ 'command_callback': 'ale_linters#tcl#nagelfar#GetCommand', \ 'callback': 'ale_linters#tcl#nagelfar#Handle', \ 'lint_file': 1, diff --git a/ale_linters/terraform/tflint.vim b/ale_linters/terraform/tflint.vim index 93966ff3..0d77835a 100644 --- a/ale_linters/terraform/tflint.vim +++ b/ale_linters/terraform/tflint.vim @@ -30,19 +30,17 @@ function! ale_linters#terraform#tflint#Handle(buffer, lines) abort return l:output endfunction -function! ale_linters#terraform#tflint#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'terraform_tflint_executable') -endfunction - function! ale_linters#terraform#tflint#GetCommand(buffer) abort - let l:cmd = ale#Escape(ale#Var(a:buffer, 'terraform_tflint_executable')) + let l:cmd = '%e' let l:config_file = ale#path#FindNearestFile(a:buffer, '.tflint.hcl') + if !empty(l:config_file) let l:cmd .= ' --config ' . ale#Escape(l:config_file) endif let l:opts = ale#Var(a:buffer, 'terraform_tflint_options') + if !empty(l:opts) let l:cmd .= ' ' . l:opts endif @@ -54,9 +52,7 @@ endfunction call ale#linter#Define('terraform', { \ 'name': 'tflint', -\ 'executable_callback': 'ale_linters#terraform#tflint#GetExecutable', +\ 'executable_callback': ale#VarFunc('terraform_tflint_executable'), \ 'command_callback': 'ale_linters#terraform#tflint#GetCommand', \ 'callback': 'ale_linters#terraform#tflint#Handle', \}) - -" vim:sw=4 diff --git a/ale_linters/tex/lacheck.vim b/ale_linters/tex/lacheck.vim index e5a9632b..5e5a94f1 100644 --- a/ale_linters/tex/lacheck.vim +++ b/ale_linters/tex/lacheck.vim @@ -1,23 +1,13 @@ " Author: Andrew Balmos - <andrew@balmos.org> " Description: lacheck for LaTeX files -let g:ale_tex_lacheck_executable = -\ get(g:, 'ale_tex_lacheck_executable', 'lacheck') - -function! ale_linters#tex#lacheck#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'tex_lacheck_executable') -endfunction - -function! ale_linters#tex#lacheck#GetCommand(buffer) abort - return ale#Var(a:buffer, 'tex_lacheck_executable') . ' %t' -endfunction +call ale#Set('tex_lacheck_executable', 'lacheck') function! ale_linters#tex#lacheck#Handle(buffer, lines) abort " Mattes lines like: " " "book.tex", line 37: possible unwanted space at "{" " "book.tex", line 38: missing `\ ' after "etc." - let l:pattern = '^".\+", line \(\d\+\): \(.\+\)$' let l:output = [] @@ -41,7 +31,7 @@ endfunction call ale#linter#Define('tex', { \ 'name': 'lacheck', -\ 'executable_callback': 'ale_linters#tex#lacheck#GetExecutable', -\ 'command_callback': 'ale_linters#tex#lacheck#GetCommand', +\ 'executable_callback': ale#VarFunc('tex_lacheck_executable'), +\ 'command': '%e %t', \ 'callback': 'ale_linters#tex#lacheck#Handle' \}) diff --git a/ale_linters/thrift/thrift.vim b/ale_linters/thrift/thrift.vim index a8fe10b6..36a8656e 100644 --- a/ale_linters/thrift/thrift.vim +++ b/ale_linters/thrift/thrift.vim @@ -2,13 +2,9 @@ call ale#Set('thrift_thrift_executable', 'thrift') call ale#Set('thrift_thrift_generators', ['cpp']) -call ale#Set('thrift_thrift_includes', []) +call ale#Set('thrift_thrift_includes', ['.']) call ale#Set('thrift_thrift_options', '-strict') -function! ale_linters#thrift#thrift#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'thrift_thrift_executable') -endfunction - function! ale_linters#thrift#thrift#GetCommand(buffer) abort let l:generators = ale#Var(a:buffer, 'thrift_thrift_generators') let l:includes = ale#Var(a:buffer, 'thrift_thrift_includes') @@ -22,7 +18,7 @@ function! ale_linters#thrift#thrift#GetCommand(buffer) abort let l:output_dir = ale#engine#CreateDirectory(a:buffer) - return ale#Escape(ale_linters#thrift#thrift#GetExecutable(a:buffer)) + return '%e' \ . ale#Pad(join(map(copy(l:generators), "'--gen ' . v:val"))) \ . ale#Pad(join(map(copy(l:includes), "'-I ' . v:val"))) \ . ale#Pad(ale#Var(a:buffer, 'thrift_thrift_options')) @@ -46,12 +42,14 @@ function! ale_linters#thrift#thrift#Handle(buffer, lines) abort let l:line = a:lines[l:index] let l:match = matchlist(l:line, l:pattern) + if empty(l:match) let l:index += 1 continue endif let l:severity = l:match[1] + if l:severity is# 'WARNING' let l:type = 'W' else @@ -61,6 +59,7 @@ function! ale_linters#thrift#thrift#Handle(buffer, lines) abort " If our text looks like "(last token was ';')", the *next* line " should contain a more descriptive error message. let l:text = l:match[4] + if l:text =~# '\(last token was .*\)' let l:index += 1 let l:text = get(a:lines, l:index, 'Unknown error ' . l:text) @@ -83,7 +82,7 @@ call ale#linter#Define('thrift', { \ 'name': 'thrift', \ 'executable': 'thrift', \ 'output_stream': 'both', -\ 'executable_callback': 'ale_linters#thrift#thrift#GetExecutable', +\ 'executable_callback': ale#VarFunc('thrift_thrift_executable'), \ 'command_callback': 'ale_linters#thrift#thrift#GetCommand', \ 'callback': 'ale_linters#thrift#thrift#Handle', \}) diff --git a/ale_linters/typescript/tsserver.vim b/ale_linters/typescript/tsserver.vim index 08bd0f41..bac63229 100644 --- a/ale_linters/typescript/tsserver.vim +++ b/ale_linters/typescript/tsserver.vim @@ -5,22 +5,13 @@ call ale#Set('typescript_tsserver_executable', 'tsserver') call ale#Set('typescript_tsserver_config_path', '') call ale#Set('typescript_tsserver_use_global', get(g:, 'ale_use_global_executables', 0)) -" These functions need to be defined just to comply with the API for LSP. -function! ale_linters#typescript#tsserver#GetProjectRoot(buffer) abort - return '' -endfunction - -function! ale_linters#typescript#tsserver#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'typescript_tsserver', [ - \ 'node_modules/.bin/tsserver', - \]) -endfunction - call ale#linter#Define('typescript', { \ 'name': 'tsserver', \ 'lsp': 'tsserver', -\ 'executable_callback': 'ale_linters#typescript#tsserver#GetExecutable', -\ 'command_callback': 'ale_linters#typescript#tsserver#GetExecutable', -\ 'project_root_callback': 'ale_linters#typescript#tsserver#GetProjectRoot', +\ 'executable_callback': ale#node#FindExecutableFunc('typescript_tsserver', [ +\ 'node_modules/.bin/tsserver', +\ ]), +\ 'command': '%e', +\ 'project_root_callback': {-> ''}, \ 'language': '', \}) diff --git a/ale_linters/vim/ale_custom_linting_rules.vim b/ale_linters/vim/ale_custom_linting_rules.vim new file mode 100644 index 00000000..3da44206 --- /dev/null +++ b/ale_linters/vim/ale_custom_linting_rules.vim @@ -0,0 +1,65 @@ +" Author: w0rp <devw0rp@gmail.com> +" Description: A linter for checking ALE project code itself. + +function! ale_linters#vim#ale_custom_linting_rules#GetExecutable(buffer) abort + let l:filename = expand('#' . a:buffer . ':p') + let l:dir_list = [] + + for l:dir in split(&runtimepath, ',') + if l:filename[:len(l:dir) - 1] is# l:dir + call add(l:dir_list, l:dir) + endif + endfor + + return !empty(l:dir_list) + \ ? findfile('test/script/custom-linting-rules', join(l:dir_list, ',')) + \ : '' +endfunction + +function! s:GetALEProjectDir(buffer) abort + let l:executable = ale_linters#vim#ale_custom_linting_rules#GetExecutable(a:buffer) + + return ale#path#Dirname(ale#path#Dirname(ale#path#Dirname(l:executable))) +endfunction + +function! ale_linters#vim#ale_custom_linting_rules#GetCommand(buffer) abort + let l:dir = s:GetALEProjectDir(a:buffer) + + let l:temp_dir = ale#engine#CreateDirectory(a:buffer) + let l:temp_file = l:temp_dir . '/example.vim' + + let l:lines = getbufline(a:buffer, 1, '$') + call ale#util#Writefile(a:buffer, l:lines, l:temp_file) + + return ale#path#CdString(l:dir) . '%e ' . ale#Escape(l:temp_dir) +endfunction + +function! ale_linters#vim#ale_custom_linting_rules#Handle(buffer, lines) abort + let l:dir = s:GetALEProjectDir(a:buffer) + let l:output = [] + let l:pattern = '\v^([a-zA-Z]?:?[^:]+):(\d+) (.+)$' + + for l:match in ale#util#GetMatches(a:lines, l:pattern) + " Ignore trailing whitespace errors if we've turned them off. + if !ale#Var(a:buffer, 'warn_about_trailing_whitespace') + \&& l:match[3] is# 'Trailing whitespace' + continue + endif + + call add(l:output, { + \ 'lnum': l:match[2], + \ 'text': l:match[3], + \ 'type': 'W', + \}) + endfor + + return l:output +endfunction + +call ale#linter#Define('vim', { +\ 'name': 'ale_custom_linting_rules', +\ 'executable_callback': 'ale_linters#vim#ale_custom_linting_rules#GetExecutable', +\ 'command_callback': 'ale_linters#vim#ale_custom_linting_rules#GetCommand', +\ 'callback': 'ale_linters#vim#ale_custom_linting_rules#Handle', +\ 'read_buffer': 0, +\}) diff --git a/ale_linters/vue/vls.vim b/ale_linters/vue/vls.vim index 0d4bf9f6..7116128b 100644 --- a/ale_linters/vue/vls.vim +++ b/ale_linters/vue/vls.vim @@ -4,18 +4,6 @@ call ale#Set('vue_vls_executable', 'vls') call ale#Set('vue_vls_use_global', get(g:, 'ale_use_global_executables', 0)) -function! ale_linters#vue#vls#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'vue_vls', [ - \ 'node_modules/.bin/vls', - \]) -endfunction - -function! ale_linters#vue#vls#GetCommand(buffer) abort - let l:exe = ale#Escape(ale_linters#vue#vls#GetExecutable(a:buffer)) - - return l:exe . ' --stdio' -endfunction - function! ale_linters#vue#vls#GetProjectRoot(buffer) abort let l:package_path = ale#path#FindNearestFile(a:buffer, 'package.json') @@ -25,8 +13,10 @@ endfunction call ale#linter#Define('vue', { \ 'name': 'vls', \ 'lsp': 'stdio', -\ 'executable_callback': 'ale_linters#vue#vls#GetExecutable', -\ 'command_callback': 'ale_linters#vue#vls#GetCommand', +\ 'executable_callback': ale#node#FindExecutableFunc('vue_vls', [ +\ 'node_modules/.bin/vls', +\ ]), +\ 'command': '%e --stdio', \ 'language': 'vue', \ 'project_root_callback': 'ale_linters#vue#vls#GetProjectRoot', \}) diff --git a/ale_linters/xml/xmllint.vim b/ale_linters/xml/xmllint.vim index 9d79438e..59f43d16 100644 --- a/ale_linters/xml/xmllint.vim +++ b/ale_linters/xml/xmllint.vim @@ -5,12 +5,8 @@ let g:ale_xml_xmllint_executable = get(g:, 'ale_xml_xmllint_executable', 'xmllint') let g:ale_xml_xmllint_options = get(g:, 'ale_xml_xmllint_options', '') -function! ale_linters#xml#xmllint#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'xml_xmllint_executable') -endfunction - function! ale_linters#xml#xmllint#GetCommand(buffer) abort - return ale#Escape(ale_linters#xml#xmllint#GetExecutable(a:buffer)) + return '%e' \ . ale#Pad(ale#Var(a:buffer, 'xml_xmllint_options')) \ . ' --noout -' endfunction @@ -29,9 +25,9 @@ function! ale_linters#xml#xmllint#Handle(buffer, lines) abort let l:output = [] for l:line in a:lines - " Parse error/warning lines let l:match_message = matchlist(l:line, l:pattern_message) + if !empty(l:match_message) let l:line = l:match_message[2] + 0 let l:type = l:match_message[4] =~? 'warning' ? 'W' : 'E' @@ -48,13 +44,13 @@ function! ale_linters#xml#xmllint#Handle(buffer, lines) abort " Parse column position let l:match_column_token = matchlist(l:line, l:pattern_column_token) + if !empty(l:output) && !empty(l:match_column_token) let l:previous = l:output[len(l:output) - 1] let l:previous['col'] = len(l:match_column_token[0]) continue endif - endfor return l:output @@ -63,7 +59,7 @@ endfunction call ale#linter#Define('xml', { \ 'name': 'xmllint', \ 'output_stream': 'stderr', -\ 'executable_callback': 'ale_linters#xml#xmllint#GetExecutable', +\ 'executable_callback': ale#VarFunc('xml_xmllint_executable'), \ 'command_callback': 'ale_linters#xml#xmllint#GetCommand', \ 'callback': 'ale_linters#xml#xmllint#Handle', \ }) diff --git a/ale_linters/yaml/swaglint.vim b/ale_linters/yaml/swaglint.vim index 4a22c70f..7362536e 100644 --- a/ale_linters/yaml/swaglint.vim +++ b/ale_linters/yaml/swaglint.vim @@ -4,17 +4,6 @@ call ale#Set('yaml_swaglint_executable', 'swaglint') call ale#Set('yaml_swaglint_use_global', get(g:, 'ale_use_global_executables', 0)) -function! ale_linters#yaml#swaglint#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'yaml_swaglint', [ - \ 'node_modules/.bin/swaglint', - \]) -endfunction - -function! ale_linters#yaml#swaglint#GetCommand(buffer) abort - return ale_linters#yaml#swaglint#GetExecutable(a:buffer) - \ . ' -r compact --stdin' -endfunction - function! ale_linters#yaml#swaglint#Handle(buffer, lines) abort let l:pattern = ': \([^\s]\+\) @ \(\d\+\):\(\d\+\) - \(.\+\)$' let l:output = [] @@ -43,7 +32,9 @@ endfunction call ale#linter#Define('yaml', { \ 'name': 'swaglint', -\ 'executable_callback': 'ale_linters#yaml#swaglint#GetExecutable', -\ 'command_callback': 'ale_linters#yaml#swaglint#GetCommand', +\ 'executable_callback': ale#node#FindExecutableFunc('yaml_swaglint', [ +\ 'node_modules/.bin/swaglint', +\ ]), +\ 'command': '%e -r compact --stdin', \ 'callback': 'ale_linters#yaml#swaglint#Handle', \}) diff --git a/ale_linters/yaml/yamllint.vim b/ale_linters/yaml/yamllint.vim index f100667e..9d2cc7c2 100644 --- a/ale_linters/yaml/yamllint.vim +++ b/ale_linters/yaml/yamllint.vim @@ -1,18 +1,10 @@ " Author: KabbAmine <amine.kabb@gmail.com> -let g:ale_yaml_yamllint_executable = -\ get(g:, 'ale_yaml_yamllint_executable', 'yamllint') - -let g:ale_yaml_yamllint_options = -\ get(g:, 'ale_yaml_yamllint_options', '') - -function! ale_linters#yaml#yamllint#GetExecutable(buffer) abort - return ale#Var(a:buffer, 'yaml_yamllint_executable') -endfunction +call ale#Set('yaml_yamllint_executable', 'yamllint') +call ale#Set('yaml_yamllint_options', '') function! ale_linters#yaml#yamllint#GetCommand(buffer) abort - return ale_linters#yaml#yamllint#GetExecutable(a:buffer) - \ . ' ' . ale#Var(a:buffer, 'yaml_yamllint_options') + return '%e' . ale#Pad(ale#Var(a:buffer, 'yaml_yamllint_options')) \ . ' -f parsable %t' endfunction @@ -52,7 +44,7 @@ endfunction call ale#linter#Define('yaml', { \ 'name': 'yamllint', -\ 'executable_callback': 'ale_linters#yaml#yamllint#GetExecutable', +\ 'executable_callback': ale#VarFunc('yaml_yamllint_executable'), \ 'command_callback': 'ale_linters#yaml#yamllint#GetCommand', \ 'callback': 'ale_linters#yaml#yamllint#Handle', \}) diff --git a/ale_linters/yang/yang_lsp.vim b/ale_linters/yang/yang_lsp.vim new file mode 100644 index 00000000..45776f98 --- /dev/null +++ b/ale_linters/yang/yang_lsp.vim @@ -0,0 +1,15 @@ +call ale#Set('yang_lsp_executable', 'yang-language-server') + +function! ale_linters#yang#yang_lsp#GetProjectRoot(buffer) abort + let l:project_root = ale#path#FindNearestFile(a:buffer, 'yang.settings') + + return !empty(l:project_root) ? fnamemodify(l:project_root, ':h') : '' +endfunction + +call ale#linter#Define('yang', { +\ 'name': 'yang_lsp', +\ 'lsp': 'stdio', +\ 'executable_callback': ale#VarFunc('yang_lsp_executable'), +\ 'project_root_callback': 'ale_linters#yang#yang_lsp#GetProjectRoot', +\ 'command': '%e', +\}) |