diff options
166 files changed, 3459 insertions, 431 deletions
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..42add447 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,36 @@ +--- +name: CI +on: # yamllint disable-line rule:truthy + push: + branches: [ master ] # yamllint disable-line rule:brackets + tags: + - /^v\d+\.\d+\.(x|\d+)$/ + pull_request: + branches: [ master ] # yamllint disable-line rule:brackets + +jobs: + build_image: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Build docker run image + shell: bash + env: + DOCKER_HUB_USER: ${{ secrets.DOCKER_HUB_USER }} + DOCKER_HUB_PASS: ${{ secrets.DOCKER_HUB_PASS }} + run: ./run-tests --build-image + test_ale: + needs: build_image + runs-on: ubuntu-latest + strategy: + matrix: + vim-version: + - '--vim-80-only' + - '--vim-82-only' + - '--neovim-02-only' + - '--neovim-04-only' + - '--linters-only' + steps: + - uses: actions/checkout@v2 + - name: Run tests + run: ./run-tests -v ${{ matrix.vim-version }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 00baff1c..00000000 --- a/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ ---- -sudo: required -services: - - docker -language: generic -branches: - only: - - master - - /^v\d+\.\d+\.(x|\d+)$/ -env: - - OPTIONS=--vim-80-only - - OPTIONS=--vim-81-only - - OPTIONS=--neovim-only - - OPTIONS=--linters-only -script: | - ./run-tests -v $OPTIONS @@ -1,15 +1,17 @@ FROM tweekmonster/vim-testbed:latest RUN install_vim -tag v8.0.0027 -build \ - -tag v8.1.0519 -build \ + -tag v8.2.2401 -build \ -tag neovim:v0.2.0 -build \ - -tag neovim:v0.3.5 -build + -tag neovim:v0.4.4 -build ENV PACKAGES="\ bash \ git \ python \ py-pip \ + grep \ + sed \ " RUN apk --update add $PACKAGES && \ rm -rf /var/cache/apk/* /tmp/* /var/tmp/* @@ -18,3 +20,7 @@ RUN pip install vim-vint==0.3.15 RUN git clone https://github.com/junegunn/vader.vim vader && \ cd vader && git checkout c6243dd81c98350df4dec608fa972df98fa2a3af + +ARG GIT_VERSION +LABEL Version=${GIT_VERSION} +LABEL Name=w0rp/ale @@ -1,4 +1,4 @@ -# Asynchronous Lint Engine [![Travis CI Build Status](https://travis-ci.com/dense-analysis/ale.svg?branch=master)](https://travis-ci.com/dense-analysis/ale) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/r0ef1xu8xjmik58d/branch/master?svg=true)](https://ci.appveyor.com/project/dense-analysis/ale) [![Join the chat at https://gitter.im/vim-ale/Lobby](https://badges.gitter.im/vim-ale/Lobby.svg)](https://gitter.im/vim-ale/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +# Asynchronous Lint Engine [![GitHub Build Status](https://github.com/dense-analysis/ale/workflows/CI/badge.svg)](https://github.com/dense-analysis/ale/actions?query=event%3Apush+workflow%3ACI+branch%3Amaster++) [![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/r0ef1xu8xjmik58d/branch/master?svg=true)](https://ci.appveyor.com/project/dense-analysis/ale) [![Join the chat at https://gitter.im/vim-ale/Lobby](https://badges.gitter.im/vim-ale/Lobby.svg)](https://gitter.im/vim-ale/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) ![ALE Logo by Mark Grealish - https://www.bhalash.com/](https://user-images.githubusercontent.com/3518142/59195920-2c339500-8b85-11e9-9c22-f6b7f69637b8.jpg) diff --git a/ale_linters/ada/adals.vim b/ale_linters/ada/adals.vim new file mode 100644 index 00000000..9a41e1df --- /dev/null +++ b/ale_linters/ada/adals.vim @@ -0,0 +1,26 @@ +" Author: Bartek Jasicki http://github.com/thindil +" Description: Support for Ada Language Server + +call ale#Set('ada_adals_executable', 'ada_language_server') +call ale#Set('ada_adals_project', 'default.gpr') +call ale#Set('ada_adals_encoding', 'utf-8') + +function! ale_linters#ada#adals#GetAdaLSConfig(buffer) abort + return { + \ 'ada.projectFile': ale#Var(a:buffer, 'ada_adals_project'), + \ 'ada.defaultCharset': ale#Var(a:buffer, 'ada_adals_encoding') + \} +endfunction + +function! ale_linters#ada#adals#GetRootDirectory(buffer) abort + return fnamemodify(bufname(a:buffer), ':p:h') +endfunction + +call ale#linter#Define('ada', { +\ 'name': 'adals', +\ 'lsp': 'stdio', +\ 'executable': {b -> ale#Var(b, 'ada_adals_executable')}, +\ 'command': '%e', +\ 'project_root': function('ale_linters#ada#adals#GetRootDirectory'), +\ 'lsp_config': function('ale_linters#ada#adals#GetAdaLSConfig') +\}) diff --git a/ale_linters/apkbuild/apkbuild_lint.vim b/ale_linters/apkbuild/apkbuild_lint.vim new file mode 100644 index 00000000..285f5534 --- /dev/null +++ b/ale_linters/apkbuild/apkbuild_lint.vim @@ -0,0 +1,12 @@ +" Author: Leo <thinkabit.ukim@gmail.com> +" Description: apkbuild-lint from atools linter for APKBUILDs + +call ale#Set('apkbuild_apkbuild_lint_executable', 'apkbuild-lint') + +call ale#linter#Define('apkbuild', { +\ 'name': 'apkbuild_lint', +\ 'output_stream': 'stdout', +\ 'executable': {b -> ale#Var(b, 'apkbuild_apkbuild_lint_executable')}, +\ 'command': '%e %t', +\ 'callback': 'ale#handlers#atools#Handle', +\}) diff --git a/ale_linters/apkbuild/secfixes_check.vim b/ale_linters/apkbuild/secfixes_check.vim new file mode 100644 index 00000000..c65267fd --- /dev/null +++ b/ale_linters/apkbuild/secfixes_check.vim @@ -0,0 +1,12 @@ +" Author: Leo <thinkabit.ukim@gmail.com> +" Description: secfixes-check from atools linter for APKBUILDs + +call ale#Set('apkbuild_secfixes_check_executable', 'secfixes-check') + +call ale#linter#Define('apkbuild', { +\ 'name': 'secfixes_check', +\ 'output_stream': 'stdout', +\ 'executable': {b -> ale#Var(b, 'apkbuild_secfixes_check_executable')}, +\ 'command': '%e %t', +\ 'callback': 'ale#handlers#atools#Handle', +\}) diff --git a/ale_linters/cloudformation/cfn_python_lint.vim b/ale_linters/cloudformation/cfn_python_lint.vim index d0ac7b28..16841431 100644 --- a/ale_linters/cloudformation/cfn_python_lint.vim +++ b/ale_linters/cloudformation/cfn_python_lint.vim @@ -29,6 +29,7 @@ endfunction call ale#linter#Define('cloudformation', { \ 'name': 'cloudformation', +\ 'aliases': ['cfn-lint'], \ 'executable': 'cfn-lint', \ 'command': 'cfn-lint --template %t --format parseable', \ 'callback': 'ale_linters#cloudformation#cfn_python_lint#Handle', diff --git a/ale_linters/cpp/clangtidy.vim b/ale_linters/cpp/clangtidy.vim index 5e062d86..d6944aae 100644 --- a/ale_linters/cpp/clangtidy.vim +++ b/ale_linters/cpp/clangtidy.vim @@ -23,11 +23,13 @@ function! ale_linters#cpp#clangtidy#GetCommand(buffer, output) abort let l:options = ale#Var(a:buffer, 'cpp_clangtidy_options') let l:cflags = ale#c#GetCFlags(a:buffer, a:output) let l:options .= !empty(l:options) ? ale#Pad(l:cflags) : l:cflags - endif - " Tell clang-tidy a .h header with a C++ filetype in Vim is a C++ file. - if expand('#' . a:buffer) =~# '\.h$' - let l:options .= !empty(l:options) ? ' -x c++' : '-x c++' + " Tell clang-tidy a .h header with a C++ filetype in Vim is a C++ file + " only when compile-commands.json file is not there. Adding these + " flags makes clang-tidy completely ignore compile commmands. + if expand('#' . a:buffer) =~# '\.h$' + let l:options .= !empty(l:options) ? ' -x c++' : '-x c++' + endif endif " Get the options to pass directly to clang-tidy diff --git a/ale_linters/dafny/dafny.vim b/ale_linters/dafny/dafny.vim index b5b90675..2a9f761a 100644 --- a/ale_linters/dafny/dafny.vim +++ b/ale_linters/dafny/dafny.vim @@ -6,7 +6,7 @@ function! ale_linters#dafny#dafny#Handle(buffer, lines) abort for l:match in ale#util#GetMatches(a:lines, l:pattern) call add(l:output, { - \ 'bufnr': a:buffer, + \ 'filename': l:match[1], \ 'col': l:match[3] + 0, \ 'lnum': l:match[2] + 0, \ 'text': l:match[5], @@ -14,13 +14,28 @@ function! ale_linters#dafny#dafny#Handle(buffer, lines) abort \ }) endfor + for l:match in ale#util#GetMatches(a:lines, '\v(.*)\((\d+),(\d+)\): (Verification of .{-} timed out after \d+ seconds)') + call add(l:output, { + \ 'filename': l:match[1], + \ 'col': l:match[3] + 0, + \ 'lnum': l:match[2] + 0, + \ 'text': l:match[4], + \ 'type': 'E', + \ }) + endfor + return l:output endfunction +function! ale_linters#dafny#dafny#GetCommand(buffer) abort + return printf('dafny %%s /compile:0 /timeLimit:%d', ale#Var(a:buffer, 'dafny_dafny_timelimit')) +endfunction + +call ale#Set('dafny_dafny_timelimit', 10) call ale#linter#Define('dafny', { \ 'name': 'dafny', \ 'executable': 'dafny', -\ 'command': 'dafny %s /compile:0', +\ 'command': function('ale_linters#dafny#dafny#GetCommand'), \ 'callback': 'ale_linters#dafny#dafny#Handle', \ 'lint_file': 1, \ }) diff --git a/ale_linters/dart/analysis_server.vim b/ale_linters/dart/analysis_server.vim new file mode 100644 index 00000000..a6870da9 --- /dev/null +++ b/ale_linters/dart/analysis_server.vim @@ -0,0 +1,29 @@ +" Author: Nelson Yeung <nelsyeung@gmail.com> +" Description: Check Dart files with dart analysis server LSP + +call ale#Set('dart_analysis_server_executable', 'dart') + +function! ale_linters#dart#analysis_server#GetProjectRoot(buffer) abort + " Note: pub only looks for pubspec.yaml, there's no point in adding + " support for pubspec.yml + let l:pubspec = ale#path#FindNearestFile(a:buffer, 'pubspec.yaml') + + return !empty(l:pubspec) ? fnamemodify(l:pubspec, ':h:h') : '.' +endfunction + +function! ale_linters#dart#analysis_server#GetCommand(buffer) abort + let l:executable = ale#Var(a:buffer, 'dart_analysis_server_executable') + let l:dart = resolve(exepath(l:executable)) + + return '%e ' + \ . fnamemodify(l:dart, ':h') . '/snapshots/analysis_server.dart.snapshot' + \ . ' --lsp' +endfunction + +call ale#linter#Define('dart', { +\ 'name': 'analysis_server', +\ 'lsp': 'stdio', +\ 'executable': {b -> ale#Var(b, 'dart_analysis_server_executable')}, +\ 'command': function('ale_linters#dart#analysis_server#GetCommand'), +\ 'project_root': function('ale_linters#dart#analysis_server#GetProjectRoot'), +\}) diff --git a/ale_linters/elixir/credo.vim b/ale_linters/elixir/credo.vim index 7c298502..892d47b9 100644 --- a/ale_linters/elixir/credo.vim +++ b/ale_linters/elixir/credo.vim @@ -45,6 +45,16 @@ function! ale_linters#elixir#credo#GetMode() abort endif endfunction +function! ale_linters#elixir#credo#GetConfigFile() abort + let l:config_file = get(g:, 'ale_elixir_credo_config_file', '') + + if empty(l:config_file) + return '' + endif + + return ' --config-file ' . l:config_file +endfunction + function! ale_linters#elixir#credo#GetCommand(buffer) abort let l:project_root = ale#handlers#elixir#FindMixUmbrellaRoot(a:buffer) let l:mode = ale_linters#elixir#credo#GetMode() @@ -52,6 +62,7 @@ function! ale_linters#elixir#credo#GetCommand(buffer) abort return ale#path#CdString(l:project_root) \ . 'mix help credo && ' \ . 'mix credo ' . ale_linters#elixir#credo#GetMode() + \ . ale_linters#elixir#credo#GetConfigFile() \ . ' --format=flycheck --read-from-stdin %s' endfunction diff --git a/ale_linters/erlang/dialyzer.vim b/ale_linters/erlang/dialyzer.vim index 395647a0..a97c9520 100644 --- a/ale_linters/erlang/dialyzer.vim +++ b/ale_linters/erlang/dialyzer.vim @@ -3,6 +3,11 @@ let g:ale_erlang_dialyzer_executable = \ get(g:, 'ale_erlang_dialyzer_executable', 'dialyzer') +let g:ale_erlang_dialyzer_options = +\ get(g:, 'ale_erlang_dialyzer_options', '-Wunmatched_returns' +\ . ' -Werror_handling' +\ . ' -Wrace_conditions' +\ . ' -Wunderspecs') let g:ale_erlang_dialyzer_plt_file = \ get(g:, 'ale_erlang_dialyzer_plt_file', '') let g:ale_erlang_dialyzer_rebar3_profile = @@ -47,13 +52,12 @@ function! ale_linters#erlang#dialyzer#GetExecutable(buffer) abort endfunction function! ale_linters#erlang#dialyzer#GetCommand(buffer) abort + let l:options = ale#Var(a:buffer, 'erlang_dialyzer_options') + let l:command = ale#Escape(ale_linters#erlang#dialyzer#GetExecutable(a:buffer)) \ . ' -n' \ . ' --plt ' . ale#Escape(ale_linters#erlang#dialyzer#GetPlt(a:buffer)) - \ . ' -Wunmatched_returns' - \ . ' -Werror_handling' - \ . ' -Wrace_conditions' - \ . ' -Wunderspecs' + \ . ' ' . l:options \ . ' %s' return l:command diff --git a/ale_linters/erlang/erlc.vim b/ale_linters/erlang/erlc.vim index a83bacc3..e78dc341 100644 --- a/ale_linters/erlang/erlc.vim +++ b/ale_linters/erlang/erlc.vim @@ -1,14 +1,22 @@ " Author: Magnus Ottenklinger - https://github.com/evnu +let g:ale_erlang_erlc_executable = get(g:, 'ale_erlang_erlc_executable', 'erlc') let g:ale_erlang_erlc_options = get(g:, 'ale_erlang_erlc_options', '') +function! ale_linters#erlang#erlc#GetExecutable(buffer) abort + return ale#Var(a:buffer, 'erlang_erlc_executable') +endfunction + function! ale_linters#erlang#erlc#GetCommand(buffer) abort let l:output_file = ale#util#Tempname() call ale#command#ManageFile(a:buffer, l:output_file) - return 'erlc -o ' . ale#Escape(l:output_file) - \ . ' ' . ale#Var(a:buffer, 'erlang_erlc_options') - \ . ' %t' + let l:command = ale#Escape(ale_linters#erlang#erlc#GetExecutable(a:buffer)) + \ . ' -o ' . ale#Escape(l:output_file) + \ . ' ' . ale#Var(a:buffer, 'erlang_erlc_options') + \ . ' %t' + + return l:command endfunction function! ale_linters#erlang#erlc#Handle(buffer, lines) abort @@ -90,7 +98,7 @@ endfunction call ale#linter#Define('erlang', { \ 'name': 'erlc', -\ 'executable': 'erlc', +\ 'executable': function('ale_linters#erlang#erlc#GetExecutable'), \ 'command': function('ale_linters#erlang#erlc#GetCommand'), \ 'callback': 'ale_linters#erlang#erlc#Handle', \}) diff --git a/ale_linters/haskell/hls.vim b/ale_linters/haskell/hls.vim new file mode 100644 index 00000000..ae0556a4 --- /dev/null +++ b/ale_linters/haskell/hls.vim @@ -0,0 +1,63 @@ +" Author: Yen3 <yen3rc@gmail.com> +" Description: A language server for haskell +" The file is based on hie.vim (author: Luxed +" <devildead13@gmail.com>). It search more project root files. +" +call ale#Set('haskell_hls_executable', 'haskell-language-server-wrapper') + +function! ale_linters#haskell#hls#FindRootFile(buffer) abort + let l:serach_root_files = [ + \ 'stack.yaml', + \ 'cabal.project', + \ 'package.yaml', + \ 'hie.yaml' + \ ] + + for l:path in ale#path#Upwards(expand('#' . a:buffer . ':p:h')) + for l:root_file in l:serach_root_files + if filereadable(l:path . l:root_file) + return l:path + endif + endfor + endfor + + return '' +endfunction + +function! ale_linters#haskell#hls#GetProjectRoot(buffer) abort + " Search for the project file first + let l:project_file = ale_linters#haskell#hls#FindRootFile(a:buffer) + + " If it's empty, search for the cabal file + if empty(l:project_file) + " Search all of the paths except for the root filesystem path. + let l:paths = join( + \ ale#path#Upwards(expand('#' . a:buffer . ':p:h'))[:-2], + \ ',' + \) + let l:project_file = globpath(l:paths, '*.cabal') + endif + + " If we still can't find one, use the current file. + if empty(l:project_file) + let l:project_file = expand('#' . a:buffer . ':p') + endif + + return fnamemodify(l:project_file, ':h') +endfunction + +function! ale_linters#haskell#hls#GetCommand(buffer) abort + let l:executable = ale#Var(a:buffer, 'haskell_hls_executable') + + return ale#handlers#haskell_stack#EscapeExecutable(l:executable, + \ 'haskell-language-server-wrapper') + \ . ' --lsp' +endfunction + +call ale#linter#Define('haskell', { +\ 'name': 'hls', +\ 'lsp': 'stdio', +\ 'command': function('ale_linters#haskell#hls#GetCommand'), +\ 'executable': {b -> ale#Var(b, 'haskell_hls_executable')}, +\ 'project_root': function('ale_linters#haskell#hls#GetProjectRoot'), +\}) diff --git a/ale_linters/inko/inko.vim b/ale_linters/inko/inko.vim new file mode 100644 index 00000000..11558897 --- /dev/null +++ b/ale_linters/inko/inko.vim @@ -0,0 +1,33 @@ +" Author: Yorick Peterse <yorick@yorickpeterse.com> +" Description: linting of Inko source code using the Inko compiler + +call ale#Set('inko_inko_executable', 'inko') + +function! ale_linters#inko#inko#GetCommand(buffer) abort + let l:include = '' + + " Include the tests source directory, but only for test files. + if expand('#' . a:buffer . ':p') =~? '\vtests[/\\]test[/\\]' + let l:test_dir = ale#path#FindNearestDirectory(a:buffer, 'tests') + + if isdirectory(l:test_dir) + let l:include = '--include ' . ale#Escape(l:test_dir) + endif + endif + + " We use %s instead of %t so the compiler determines the correct module + " names for the file being edited. Not doing so may lead to errors in + " certain cases. + return '%e build --check --format=json' + \ . ale#Pad(l:include) + \ . ' %s' +endfunction + +call ale#linter#Define('inko', { +\ 'name': 'inko', +\ 'executable': {b -> ale#Var(b, 'inko_inko_executable')}, +\ 'command': function('ale_linters#inko#inko#GetCommand'), +\ 'callback': 'ale#handlers#inko#Handle', +\ 'output_stream': 'stderr', +\ 'lint_file': 1 +\}) diff --git a/ale_linters/java/checkstyle.vim b/ale_linters/java/checkstyle.vim index ec7339d1..f00734e0 100644 --- a/ale_linters/java/checkstyle.vim +++ b/ale_linters/java/checkstyle.vim @@ -9,7 +9,7 @@ function! ale_linters#java#checkstyle#Handle(buffer, lines) abort let l:output = [] " modern checkstyle versions - let l:pattern = '\v\[(WARN|ERROR)\] [a-zA-Z]?:?[^:]+:(\d+):(\d+)?:? (.*) \[(.+)\]$' + let l:pattern = '\v\[(WARN|ERROR)\] [a-zA-Z]?:?[^:]+:(\d+):(\d+)?:? (.*) \[(.+)\]' for l:match in ale#util#GetMatches(a:lines, l:pattern) call add(l:output, { diff --git a/ale_linters/java/eclipselsp.vim b/ale_linters/java/eclipselsp.vim index 8bc09039..adfd1b09 100644 --- a/ale_linters/java/eclipselsp.vim +++ b/ale_linters/java/eclipselsp.vim @@ -29,28 +29,28 @@ function! ale_linters#java#eclipselsp#JarPath(buffer) abort endif " Search jar file within repository path when manually built using mvn - let l:files = globpath(l:path, '**/'.l:platform.'/**/plugins/org.eclipse.equinox.launcher_\d\.\d\.\d\d\d\.*\.jar', 1, 1) + let l:files = globpath(l:path, '**/'.l:platform.'/**/plugins/org.eclipse.equinox.launcher_*\.jar', 1, 1) if len(l:files) >= 1 return l:files[0] endif " Search jar file within VSCode extensions folder. - let l:files = globpath(l:path, '**/'.l:platform.'/plugins/org.eclipse.equinox.launcher_\d\.\d\.\d\d\d\.*\.jar', 1, 1) + let l:files = globpath(l:path, '**/'.l:platform.'/plugins/org.eclipse.equinox.launcher_*\.jar', 1, 1) if len(l:files) >= 1 return l:files[0] endif " Search jar file within unzipped tar.gz file - let l:files = globpath(l:path, 'plugins/org.eclipse.equinox.launcher_\d\.\d\.\d\d\d\.*\.jar', 1, 1) + let l:files = globpath(l:path, 'plugins/org.eclipse.equinox.launcher_*\.jar', 1, 1) if len(l:files) >= 1 return l:files[0] endif " Search jar file within system package path - let l:files = globpath('/usr/share/java/jdtls/plugins', 'org.eclipse.equinox.launcher_\d\.\d\.\d\d\d\.*\.jar', 1, 1) + let l:files = globpath('/usr/share/java/jdtls/plugins', 'org.eclipse.equinox.launcher_*\.jar', 1, 1) if len(l:files) >= 1 return l:files[0] diff --git a/ale_linters/javascript/xo.vim b/ale_linters/javascript/xo.vim index e24f4a82..5e04ad5c 100644 --- a/ale_linters/javascript/xo.vim +++ b/ale_linters/javascript/xo.vim @@ -1,26 +1,9 @@ " Author: Daniel Lupu <lupu.daniel.f@gmail.com> " Description: xo for JavaScript files -call ale#Set('javascript_xo_executable', 'xo') -call ale#Set('javascript_xo_use_global', get(g:, 'ale_use_global_executables', 0)) -call ale#Set('javascript_xo_options', '') - -function! ale_linters#javascript#xo#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'javascript_xo', [ - \ 'node_modules/.bin/xo', - \]) -endfunction - -function! ale_linters#javascript#xo#GetCommand(buffer) abort - return ale#Escape(ale_linters#javascript#xo#GetExecutable(a:buffer)) - \ . ' ' . ale#Var(a:buffer, 'javascript_xo_options') - \ . ' --reporter json --stdin --stdin-filename %s' -endfunction - -" xo uses eslint and the output format is the same call ale#linter#Define('javascript', { \ 'name': 'xo', -\ 'executable': function('ale_linters#javascript#xo#GetExecutable'), -\ 'command': function('ale_linters#javascript#xo#GetCommand'), -\ 'callback': 'ale#handlers#eslint#HandleJSON', +\ 'executable': function('ale#handlers#xo#GetExecutable'), +\ 'command': function('ale#handlers#xo#GetLintCommand'), +\ 'callback': 'ale#handlers#xo#HandleJSON', \}) diff --git a/ale_linters/json/spectral.vim b/ale_linters/json/spectral.vim new file mode 100644 index 00000000..c7d56234 --- /dev/null +++ b/ale_linters/json/spectral.vim @@ -0,0 +1,14 @@ +" Author: t2h5 <https://github.com/t2h5> +" Description: Integration of Stoplight Spectral CLI with ALE. + +call ale#Set('json_spectral_executable', 'spectral') +call ale#Set('json_spectral_use_global', get(g:, 'ale_use_global_executables', 0)) + +call ale#linter#Define('json', { +\ 'name': 'spectral', +\ 'executable': {b -> ale#node#FindExecutable(b, 'json_spectral', [ +\ 'node_modules/.bin/spectral', +\ ])}, +\ 'command': '%e lint --ignore-unknown-format -q -f text %t', +\ 'callback': 'ale#handlers#spectral#HandleSpectralOutput' +\}) diff --git a/ale_linters/julia/languageserver.vim b/ale_linters/julia/languageserver.vim index 564bec39..999ad815 100644 --- a/ale_linters/julia/languageserver.vim +++ b/ale_linters/julia/languageserver.vim @@ -6,9 +6,9 @@ call ale#Set('julia_executable', 'julia') function! ale_linters#julia#languageserver#GetCommand(buffer) abort let l:julia_executable = ale#Var(a:buffer, 'julia_executable') - let l:cmd_string = 'using LanguageServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, false); server.runlinter = true; run(server);' + let l:cmd_string = 'using LanguageServer; using Pkg; import StaticLint; import SymbolServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, dirname(Pkg.Types.Context().env.project_file)); server.runlinter = true; run(server);' - return ale#Escape(l:julia_executable) . ' --startup-file=no --history-file=no -e ' . ale#Escape(l:cmd_string) + return ale#Escape(l:julia_executable) . ' --project=@. --startup-file=no --history-file=no -e ' . ale#Escape(l:cmd_string) endfunction call ale#linter#Define('julia', { diff --git a/ale_linters/nix/nix.vim b/ale_linters/nix/nix.vim index 0a0c5c3e..3d91a9ec 100644 --- a/ale_linters/nix/nix.vim +++ b/ale_linters/nix/nix.vim @@ -1,18 +1,51 @@ " Author: Alistair Bill <@alibabzo> +" Author: Maximilian Bosch <maximilian@mbosch.me> " Description: nix-instantiate linter for nix files +function! ale_linters#nix#nix#Command(buffer, output, meta) abort + let l:version = a:output[0][22:] + + if l:version =~# '^\(2.4\|3\).*' + return 'nix-instantiate --log-format internal-json --parse -' + else + return 'nix-instantiate --parse -' + endif +endfunction + function! ale_linters#nix#nix#Handle(buffer, lines) abort - let l:pattern = '^\(.\+\): \(.\+\), at .*:\(\d\+\):\(\d\+\)$' let l:output = [] - for l:match in ale#util#GetMatches(a:lines, l:pattern) - call add(l:output, { - \ 'lnum': l:match[3] + 0, - \ 'col': l:match[4] + 0, - \ 'text': l:match[1] . ': ' . l:match[2], - \ 'type': l:match[1] =~# '^error' ? 'E' : 'W', - \}) - endfor + if empty(a:lines) + return l:output + endif + + if a:lines[0] =~# '^@nix .*' + for l:line in a:lines + if l:line =~# '^@nix .*' + let l:result = json_decode(strpart(l:line, 4)) + + if has_key(l:result, 'column') + call add(l:output, { + \ 'type': 'E', + \ 'lnum': l:result.line, + \ 'col': l:result.column, + \ 'text': l:result.raw_msg + \}) + endif + endif + endfor + else + let l:pattern = '^\(.\+\): \(.\+\) at .*:\(\d\+\):\(\d\+\)$' + + for l:match in ale#util#GetMatches(a:lines, l:pattern) + call add(l:output, { + \ 'lnum': l:match[3] + 0, + \ 'col': l:match[4] + 0, + \ 'text': l:match[1] . ': ' . substitute(l:match[2], ',$', '', ''), + \ 'type': l:match[1] =~# '^error' ? 'E' : 'W', + \}) + endfor + endif return l:output endfunction @@ -21,6 +54,10 @@ call ale#linter#Define('nix', { \ 'name': 'nix', \ 'output_stream': 'stderr', \ 'executable': 'nix-instantiate', -\ 'command': 'nix-instantiate --parse -', +\ 'command': {buffer -> ale#command#Run( +\ buffer, +\ 'nix-instantiate --version', +\ function('ale_linters#nix#nix#Command') +\ )}, \ 'callback': 'ale_linters#nix#nix#Handle', \}) diff --git a/ale_linters/nix/rnix_lsp.vim b/ale_linters/nix/rnix_lsp.vim new file mode 100644 index 00000000..949bed1c --- /dev/null +++ b/ale_linters/nix/rnix_lsp.vim @@ -0,0 +1,16 @@ +" Author: jD91mZM2 <me@krake.one> +" Description: rnix-lsp language client + +function! ale_linters#nix#rnix_lsp#GetProjectRoot(buffer) abort + " rnix-lsp does not yet use the project root, so getting it right is not + " important + return fnamemodify(a:buffer, ':h') +endfunction + +call ale#linter#Define('nix', { +\ 'name': 'rnix_lsp', +\ 'lsp': 'stdio', +\ 'executable': 'rnix-lsp', +\ 'command': '%e', +\ 'project_root': function('ale_linters#nix#rnix_lsp#GetProjectRoot'), +\}) diff --git a/ale_linters/openapi/ibm_validator.vim b/ale_linters/openapi/ibm_validator.vim new file mode 100644 index 00000000..446931a2 --- /dev/null +++ b/ale_linters/openapi/ibm_validator.vim @@ -0,0 +1,58 @@ +" Author: Horacio Sanson <hsanson@gmail.com> + +call ale#Set('openapi_ibm_validator_executable', 'lint-openapi') +call ale#Set('openapi_ibm_validator_options', '') + +function! ale_linters#openapi#ibm_validator#GetCommand(buffer) abort + return '%e' . ale#Pad(ale#Var(a:buffer, 'openapi_ibm_validator_options')) + \ . ' %t' +endfunction + +function! ale_linters#openapi#ibm_validator#Handle(buffer, lines) abort + let l:output = [] + let l:type = 'E' + let l:message = '' + let l:nr = -1 + + for l:line in a:lines + let l:match = matchlist(l:line, '^errors$') + + if !empty(l:match) + let l:type = 'E' + endif + + let l:match = matchlist(l:line, '^warnings$') + + if !empty(l:match) + let l:type = 'W' + endif + + let l:match = matchlist(l:line, '^ *Message : *\(.\+\)$') + + if !empty(l:match) + let l:message = l:match[1] + endif + + let l:match = matchlist(l:line, '^ *Line *: *\(\d\+\)$') + + if !empty(l:match) + let l:nr = l:match[1] + + call add(l:output, { + \ 'lnum': l:nr + 0, + \ 'col': 0, + \ 'text': l:message, + \ 'type': l:type, + \}) + endif + endfor + + return l:output +endfunction + +call ale#linter#Define('openapi', { +\ 'name': 'ibm_validator', +\ 'executable': {b -> ale#Var(b, 'openapi_ibm_validator_executable')}, +\ 'command': function('ale_linters#openapi#ibm_validator#GetCommand'), +\ 'callback': 'ale_linters#openapi#ibm_validator#Handle', +\}) diff --git a/ale_linters/openapi/yamllint.vim b/ale_linters/openapi/yamllint.vim new file mode 100644 index 00000000..2b8952cc --- /dev/null +++ b/ale_linters/openapi/yamllint.vim @@ -0,0 +1,9 @@ +call ale#Set('yaml_yamllint_executable', 'yamllint') +call ale#Set('yaml_yamllint_options', '') + +call ale#linter#Define('openapi', { +\ 'name': 'yamllint', +\ 'executable': {b -> ale#Var(b, 'yaml_yamllint_executable')}, +\ 'command': function('ale#handlers#yamllint#GetCommand'), +\ 'callback': 'ale#handlers#yamllint#Handle', +\}) diff --git a/ale_linters/perl6/perl6.vim b/ale_linters/perl6/perl6.vim index 68ef4769..444ae4d7 100644 --- a/ale_linters/perl6/perl6.vim +++ b/ale_linters/perl6/perl6.vim @@ -88,7 +88,7 @@ function! ale_linters#perl6#perl6#Handle(buffer, lines) abort try let l:json = json_decode(join(a:lines, '')) - catch /E474/ + catch /E474\|E491/ call add(l:output, { \ 'lnum': '1', \ 'text': 'Received output in the default Perl6 error format. See :ALEDetail for details', diff --git a/ale_linters/php/intelephense.vim b/ale_linters/php/intelephense.vim index e9e07d1f..aca619e3 100644..100755 --- a/ale_linters/php/intelephense.vim +++ b/ale_linters/php/intelephense.vim @@ -18,8 +18,8 @@ function! ale_linters#php#intelephense#GetProjectRoot(buffer) abort return !empty(l:git_path) ? fnamemodify(l:git_path, ':h:h') : '' endfunction -function! ale_linters#php#intelephense#GetInitializationOptions() abort - return ale#Get('php_intelephense_config') +function! ale_linters#php#intelephense#GetInitializationOptions(buffer) abort + return ale#Var(a:buffer, 'php_intelephense_config') endfunction call ale#linter#Define('php', { diff --git a/ale_linters/prolog/swipl.vim b/ale_linters/prolog/swipl.vim index 5c601c40..82859eb0 100644 --- a/ale_linters/prolog/swipl.vim +++ b/ale_linters/prolog/swipl.vim @@ -35,10 +35,11 @@ function! s:Subst(format, vars) abort 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 + let l:pattern = '\v^(ERROR|Warning)+%(:\s*[^:]+:(\d+)%(:(\d+))?)?:\s*(.*)$' + while l:i < len(a:lines) let l:match = matchlist(a:lines[l:i], l:pattern) @@ -72,8 +73,17 @@ function! s:GetErrMsg(i, lines, text) abort 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:pattern = '\v^(ERROR|Warning)?:?(.*)$' + + while l:i < len(a:lines) + let l:match = matchlist(a:lines[l:i], l:pattern) + + if empty(l:match) || empty(l:match[2]) + let l:i += 1 + break + endif + + call add(l:text, s:Trim(l:match[2])) let l:i += 1 endwhile diff --git a/ale_linters/ruby/sorbet.vim b/ale_linters/ruby/sorbet.vim index cae0683c..c67e20cc 100644 --- a/ale_linters/ruby/sorbet.vim +++ b/ale_linters/ruby/sorbet.vim @@ -1,14 +1,17 @@ call ale#Set('ruby_sorbet_executable', 'srb') call ale#Set('ruby_sorbet_options', '') +call ale#Set('ruby_sorbet_enable_watchman', 0) function! ale_linters#ruby#sorbet#GetCommand(buffer) abort let l:executable = ale#Var(a:buffer, 'ruby_sorbet_executable') let l:options = ale#Var(a:buffer, 'ruby_sorbet_options') + let l:enable_watchman = ale#Var(a:buffer, 'ruby_sorbet_enable_watchman') return ale#ruby#EscapeExecutable(l:executable, 'srb') \ . ' tc' \ . (!empty(l:options) ? ' ' . l:options : '') - \ . ' --lsp --disable-watchman' + \ . ' --lsp' + \ . (l:enable_watchman ? '' : ' --disable-watchman') endfunction call ale#linter#Define('ruby', { diff --git a/ale_linters/rust/analyzer.vim b/ale_linters/rust/analyzer.vim index 3666ec03..77d946f7 100644 --- a/ale_linters/rust/analyzer.vim +++ b/ale_linters/rust/analyzer.vim @@ -17,7 +17,7 @@ endfunction call ale#linter#Define('rust', { \ 'name': 'analyzer', \ 'lsp': 'stdio', -\ 'lsp_config': {b -> ale#Var(b, 'rust_analyzer_config')}, +\ 'initialization_options': {b -> ale#Var(b, 'rust_analyzer_config')}, \ 'executable': {b -> ale#Var(b, 'rust_analyzer_executable')}, \ 'command': function('ale_linters#rust#analyzer#GetCommand'), \ 'project_root': function('ale_linters#rust#analyzer#GetProjectRoot'), diff --git a/ale_linters/salt/salt_lint.vim b/ale_linters/salt/salt_lint.vim new file mode 100644 index 00000000..47f66d83 --- /dev/null +++ b/ale_linters/salt/salt_lint.vim @@ -0,0 +1,33 @@ +" Author: Benjamin BINIER <poulpatine@gmail.com> +" Description: salt-lint, saltstack linter + +call ale#Set('salt_salt_lint_executable', 'salt-lint') +call ale#Set('salt_salt_lint_options', '') + +function! ale_linters#salt#salt_lint#GetCommand(buffer) abort + return '%e' . ale#Pad(ale#Var(a:buffer, 'salt_salt_lint_options')) + \ . ' --json' +endfunction + +function! ale_linters#salt#salt_lint#Handle(buffer, lines) abort + let l:output = [] + + for l:error in ale#util#FuzzyJSONDecode(a:lines, []) + call add(l:output, { + \ 'lnum': l:error.linenumber + 0, + \ 'code': l:error.id + 0, + \ 'text': l:error.message, + \ 'type': l:error.severity is# 'HIGH' ? 'E' : 'W', + \}) + endfor + + return l:output +endfunction + +call ale#linter#Define('salt', { +\ 'name': 'salt_lint', +\ 'aliases': ['salt-lint'], +\ 'executable': {b -> ale#Var(b, 'salt_salt_lint_executable')}, +\ 'command': function('ale_linters#salt#salt_lint#GetCommand'), +\ 'callback': 'ale_linters#salt#salt_lint#Handle' +\}) diff --git a/ale_linters/terraform/terraform.vim b/ale_linters/terraform/terraform.vim index 0429cb7a..623fc2fd 100644 --- a/ale_linters/terraform/terraform.vim +++ b/ale_linters/terraform/terraform.vim @@ -9,30 +9,40 @@ endfunction function! ale_linters#terraform#terraform#GetCommand(buffer) abort return ale#Escape(ale_linters#terraform#terraform#GetExecutable(a:buffer)) - \ . ' fmt -no-color --check=true -' + \ . ' validate -no-color -json ' +endfunction + +function! ale_linters#terraform#terraform#GetType(severity) abort + if a:severity is? 'warning' + return 'W' + endif + + return 'E' endfunction function! ale_linters#terraform#terraform#Handle(buffer, lines) abort - let l:head = '^Error running fmt: In <standard input>: ' let l:output = [] - let l:patterns = [ - \ l:head.'At \(\d\+\):\(\d\+\): \(.*\)$', - \ l:head.'\(.*\)$' - \] - for l:match in ale#util#GetMatches(a:lines, l:patterns) - if len(l:match[2]) > 0 + let l:errors = ale#util#FuzzyJSONDecode(a:lines, {'diagnostics': []}) + let l:dir = expand('#' . a:buffer . ':p:h') + let l:file = expand('#' . a:buffer . ':p') + + for l:error in l:errors['diagnostics'] + if has_key(l:error, 'range') call add(l:output, { - \ 'lnum': str2nr(l:match[1]), - \ 'col': str2nr(l:match[2]), - \ 'text': l:match[3], - \ 'type': 'E', + \ 'filename': ale#path#GetAbsPath(l:dir, l:error['range']['filename']), + \ 'lnum': l:error['range']['start']['line'], + \ 'col': l:error['range']['start']['column'], + \ 'text': l:error['detail'], + \ 'type': ale_linters#terraform#terraform#GetType(l:error['severity']), \}) else call add(l:output, { - \ 'lnum': line('$'), - \ 'text': l:match[1], - \ 'type': 'E', + \ 'filename': l:file, + \ 'lnum': 0, + \ 'col': 0, + \ 'text': l:error['detail'], + \ 'type': ale_linters#terraform#terraform#GetType(l:error['severity']), \}) endif endfor @@ -42,7 +52,7 @@ endfunction call ale#linter#Define('terraform', { \ 'name': 'terraform', -\ 'output_stream': 'stderr', +\ 'output_stream': 'stdout', \ 'executable': function('ale_linters#terraform#terraform#GetExecutable'), \ 'command': function('ale_linters#terraform#terraform#GetCommand'), \ 'callback': 'ale_linters#terraform#terraform#Handle', diff --git a/ale_linters/terraform/terraform_ls.vim b/ale_linters/terraform/terraform_ls.vim new file mode 100644 index 00000000..ab35126e --- /dev/null +++ b/ale_linters/terraform/terraform_ls.vim @@ -0,0 +1,38 @@ +" Author: Horacio Sanson <hsanson@gmail.com> +" Description: terraform-ls integration for ALE (cf. https://github.com/hashicorp/terraform-ls) + +call ale#Set('terraform_terraform_executable', 'terraform') +call ale#Set('terraform_ls_executable', 'terraform-ls') +call ale#Set('terraform_ls_options', '') + +function! ale_linters#terraform#terraform_ls#GetTerraformExecutable(buffer) abort + let l:terraform_executable = ale#Var(a:buffer, 'terraform_terraform_executable') + + if(ale#path#IsAbsolute(l:terraform_executable)) + return '-tf-exec ' . l:terraform_executable + endif + + return '' +endfunction + +function! ale_linters#terraform#terraform_ls#GetCommand(buffer) abort + return '%e' + \ . ale#Pad('serve') + \ . ale#Pad(ale_linters#terraform#terraform_ls#GetTerraformExecutable(a:buffer)) + \ . ale#Pad(ale#Var(a:buffer, 'terraform_ls_options')) +endfunction + +function! ale_linters#terraform#terraform_ls#GetProjectRoot(buffer) abort + let l:tf_dir = ale#path#FindNearestDirectory(a:buffer, '.terraform') + + return !empty(l:tf_dir) ? fnamemodify(l:tf_dir, ':h:h') : '' +endfunction + +call ale#linter#Define('terraform', { +\ 'name': 'terraform_ls', +\ 'lsp': 'stdio', +\ 'executable': {b -> ale#Var(b, 'terraform_ls_executable')}, +\ 'command': function('ale_linters#terraform#terraform_ls#GetCommand'), +\ 'project_root': function('ale_linters#terraform#terraform_ls#GetProjectRoot'), +\ 'language': 'terraform', +\}) diff --git a/ale_linters/typescript/deno.vim b/ale_linters/typescript/deno.vim new file mode 100644 index 00000000..051cb208 --- /dev/null +++ b/ale_linters/typescript/deno.vim @@ -0,0 +1,25 @@ +" Author: Mohammed Chelouti - https://github.com/motato1 +" Description: Deno lsp linter for TypeScript files. + +call ale#linter#Define('typescript', { +\ 'name': 'deno', +\ 'lsp': 'stdio', +\ 'executable': function('ale#handlers#deno#GetExecutable'), +\ 'command': '%e lsp', +\ 'project_root': function('ale#handlers#deno#GetProjectRoot'), +\ 'initialization_options': function('ale_linters#typescript#deno#GetInitializationOptions'), +\}) + +function! ale_linters#typescript#deno#GetInitializationOptions(buffer) abort + let l:options = { + \ 'enable': v:true, + \ 'lint': v:true, + \ 'unstable': v:false, + \ } + + if ale#Var(a:buffer, 'deno_unstable') + let l:options.unstable = v:true + endif + + return l:options +endfunction diff --git a/ale_linters/typescript/xo.vim b/ale_linters/typescript/xo.vim index 0a3a717b..6f4ee50c 100644 --- a/ale_linters/typescript/xo.vim +++ b/ale_linters/typescript/xo.vim @@ -1,23 +1,6 @@ -call ale#Set('typescript_xo_executable', 'xo') -call ale#Set('typescript_xo_use_global', get(g:, 'ale_use_global_executables', 0)) -call ale#Set('typescript_xo_options', '') - -function! ale_linters#typescript#xo#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'typescript_xo', [ - \ 'node_modules/.bin/xo', - \]) -endfunction - -function! ale_linters#typescript#xo#GetCommand(buffer) abort - return ale#Escape(ale_linters#typescript#xo#GetExecutable(a:buffer)) - \ . ale#Pad(ale#Var(a:buffer, 'typescript_xo_options')) - \ . ' --reporter json --stdin --stdin-filename %s' -endfunction - -" xo uses eslint and the output format is the same call ale#linter#Define('typescript', { \ 'name': 'xo', -\ 'executable': function('ale_linters#typescript#xo#GetExecutable'), -\ 'command': function('ale_linters#typescript#xo#GetCommand'), -\ 'callback': 'ale#handlers#eslint#HandleJSON', +\ 'executable': function('ale#handlers#xo#GetExecutable'), +\ 'command': function('ale#handlers#xo#GetLintCommand'), +\ 'callback': 'ale#handlers#xo#HandleJSON', \}) diff --git a/ale_linters/vala/vala_lint.vim b/ale_linters/vala/vala_lint.vim new file mode 100644 index 00000000..7f8a566a --- /dev/null +++ b/ale_linters/vala/vala_lint.vim @@ -0,0 +1,66 @@ +" Author: Atsuya Takagi <asoftonight@gmail.com> +" Description: A linter for Vala using Vala-Lint. + +call ale#Set('vala_vala_lint_config_filename', 'vala-lint.conf') +call ale#Set('vala_vala_lint_executable', 'io.elementary.vala-lint') + +function! ale_linters#vala#vala_lint#GetExecutable(buffer) abort + return ale#Var(a:buffer, 'vala_vala_lint_executable') +endfunction + +function! ale_linters#vala#vala_lint#GetCommand(buffer) abort + let l:command = ale_linters#vala#vala_lint#GetExecutable(a:buffer) + + let l:config_filename = ale#Var(a:buffer, 'vala_vala_lint_config_filename') + let l:config_path = ale#path#FindNearestFile(a:buffer, l:config_filename) + + if !empty(l:config_path) + let l:command .= ' -c ' . l:config_path + endif + + return l:command . ' %s' +endfunction + +function! ale_linters#vala#vala_lint#Handle(buffer, lines) abort + let l:pattern = '^\s*\(\d\+\)\.\(\d\+\)\s\+\(error\|warn\)\s\+\(.\+\)\s\([A-Za-z0-9_\-]\+\)' + let l:output = [] + + for l:line in a:lines + " remove color escape sequences since vala-lint doesn't support + " output without colors + let l:cleaned_line = substitute(l:line, '\e\[[0-9;]\+[mK]', '', 'g') + let l:match = matchlist(l:cleaned_line, l:pattern) + + if len(l:match) == 0 + continue + endif + + let l:refined_type = l:match[3] is# 'warn' ? 'W' : 'E' + let l:cleaned_text = substitute(l:match[4], '^\s*\(.\{-}\)\s*$', '\1', '') + + let l:lnum = l:match[1] + 0 + let l:column = l:match[2] + 0 + let l:type = l:refined_type + let l:text = l:cleaned_text + let l:code = l:match[5] + + call add(l:output, { + \ 'lnum': l:lnum, + \ 'col': l:column, + \ 'text': l:text, + \ 'type': l:type, + \ 'code': l:code, + \}) + endfor + + return l:output +endfunction + +call ale#linter#Define('vala', { +\ 'name': 'vala_lint', +\ 'output_stream': 'stdout', +\ 'executable': function('ale_linters#vala#vala_lint#GetExecutable'), +\ 'command': function('ale_linters#vala#vala_lint#GetCommand'), +\ 'callback': 'ale_linters#vala#vala_lint#Handle', +\ 'lint_file': 1, +\}) diff --git a/ale_linters/yaml/spectral.vim b/ale_linters/yaml/spectral.vim new file mode 100644 index 00000000..bd4623a5 --- /dev/null +++ b/ale_linters/yaml/spectral.vim @@ -0,0 +1,14 @@ +" Author: t2h5 <https://github.com/t2h5> +" Description: Integration of Stoplight Spectral CLI with ALE. + +call ale#Set('yaml_spectral_executable', 'spectral') +call ale#Set('yaml_spectral_use_global', get(g:, 'ale_use_global_executables', 0)) + +call ale#linter#Define('yaml', { +\ 'name': 'spectral', +\ 'executable': {b -> ale#node#FindExecutable(b, 'yaml_spectral', [ +\ 'node_modules/.bin/spectral', +\ ])}, +\ 'command': '%e lint --ignore-unknown-format -q -f text %t', +\ 'callback': 'ale#handlers#spectral#HandleSpectralOutput' +\}) diff --git a/ale_linters/yaml/yamllint.vim b/ale_linters/yaml/yamllint.vim index bedb7bf1..39011df1 100644 --- a/ale_linters/yaml/yamllint.vim +++ b/ale_linters/yaml/yamllint.vim @@ -3,48 +3,9 @@ call ale#Set('yaml_yamllint_executable', 'yamllint') call ale#Set('yaml_yamllint_options', '') -function! ale_linters#yaml#yamllint#GetCommand(buffer) abort - return '%e' . ale#Pad(ale#Var(a:buffer, 'yaml_yamllint_options')) - \ . ' -f parsable %t' -endfunction - -function! ale_linters#yaml#yamllint#Handle(buffer, lines) abort - " Matches patterns line the following: - " something.yaml:1:1: [warning] missing document start "---" (document-start) - " something.yml:2:1: [error] syntax error: expected the node content, but found '<stream end>' - let l:pattern = '\v^.*:(\d+):(\d+): \[(error|warning)\] (.+)$' - let l:output = [] - - for l:match in ale#util#GetMatches(a:lines, l:pattern) - let l:item = { - \ 'lnum': l:match[1] + 0, - \ 'col': l:match[2] + 0, - \ 'text': l:match[4], - \ 'type': l:match[3] is# 'error' ? 'E' : 'W', - \} - - let l:code_match = matchlist(l:item.text, '\v^(.+) \(([^)]+)\)$') - - if !empty(l:code_match) - if l:code_match[2] is# 'trailing-spaces' - \&& !ale#Var(a:buffer, 'warn_about_trailing_whitespace') - " Skip warnings for trailing whitespace if the option is off. - continue - endif - - let l:item.text = l:code_match[1] - let l:item.code = l:code_match[2] - endif - - call add(l:output, l:item) - endfor - - return l:output -endfunction - call ale#linter#Define('yaml', { \ 'name': 'yamllint', \ 'executable': {b -> ale#Var(b, 'yaml_yamllint_executable')}, -\ 'command': function('ale_linters#yaml#yamllint#GetCommand'), -\ 'callback': 'ale_linters#yaml#yamllint#Handle', +\ 'command': function('ale#handlers#yamllint#GetCommand'), +\ 'callback': 'ale#handlers#yamllint#Handle', \}) diff --git a/autoload/ale/c.vim b/autoload/ale/c.vim index cff53125..c7b1e20a 100644 --- a/autoload/ale/c.vim +++ b/autoload/ale/c.vim @@ -152,6 +152,7 @@ function! ale#c#ParseCFlags(path_prefix, should_quote, raw_arguments) abort \ || stridx(l:option, '-idirafter') == 0 \ || stridx(l:option, '-iframework') == 0 \ || stridx(l:option, '-include') == 0 + \ || stridx(l:option, '-imacros') == 0 if stridx(l:option, '-I') == 0 && l:option isnot# '-I' let l:arg = join(split(l:option, '\zs')[2:], '') let l:option = '-I' diff --git a/autoload/ale/codefix.vim b/autoload/ale/codefix.vim index 69bf36fa..4a78063b 100644 --- a/autoload/ale/codefix.vim +++ b/autoload/ale/codefix.vim @@ -261,7 +261,10 @@ function! ale#codefix#HandleLSPResponse(conn_id, response) abort " Send the results to the menu callback, if set. if l:MenuCallback isnot v:null - call l:MenuCallback(map(copy(l:result), '[''lsp'', v:val]')) + call l:MenuCallback( + \ l:data, + \ map(copy(l:result), '[''lsp'', v:val]') + \) return endif diff --git a/autoload/ale/completion.vim b/autoload/ale/completion.vim index 39bfc094..332d0734 100644 --- a/autoload/ale/completion.vim +++ b/autoload/ale/completion.vim @@ -614,6 +614,8 @@ function! ale#completion#ParseLSPCompletions(response) abort \ 'kind': ale#completion#GetCompletionSymbols(get(l:item, 'kind', '')), \ 'icase': 1, \ 'menu': l:detail, + \ 'dup': get(l:info, 'additional_edits_only', 0) + \ || g:ale_completion_autoimport, \ 'info': (type(l:doc) is v:t_string ? l:doc : ''), \} " This flag is used to tell if this completion came from ALE or not. diff --git a/autoload/ale/cursor.vim b/autoload/ale/cursor.vim index 9ca6fb15..e8478e93 100644 --- a/autoload/ale/cursor.vim +++ b/autoload/ale/cursor.vim @@ -9,7 +9,6 @@ let g:ale_echo_delay = get(g:, 'ale_echo_delay', 10) let g:ale_echo_msg_format = get(g:, 'ale_echo_msg_format', '%code: %%s') let s:cursor_timer = -1 -let s:last_pos = [0, 0, 0] function! ale#cursor#TruncatedEcho(original_message) abort let l:message = a:original_message @@ -118,14 +117,18 @@ function! ale#cursor#EchoCursorWarningWithDelay() abort let l:pos = getpos('.')[0:2] + if !exists('w:last_pos') + let w:last_pos = [0, 0, 0] + endif + " Check the current buffer, line, and column number against the last " recorded position. If the position has actually changed, *then* " we should echo something. Otherwise we can end up doing processing " the echo message far too frequently. - if l:pos != s:last_pos + if l:pos != w:last_pos let l:delay = ale#Var(l:buffer, 'echo_delay') - let s:last_pos = l:pos + let w:last_pos = l:pos let s:cursor_timer = timer_start( \ l:delay, \ function('ale#cursor#EchoCursorWarning') @@ -139,11 +142,16 @@ function! s:ShowCursorDetailForItem(loc, options) abort let s:last_detailed_line = line('.') let l:message = get(a:loc, 'detail', a:loc.text) let l:lines = split(l:message, "\n") - call ale#preview#Show(l:lines, {'stay_here': l:stay_here}) - " Clear the echo message if we manually displayed details. - if !l:stay_here - execute 'echo' + if g:ale_floating_preview || g:ale_detail_to_floating_preview + call ale#floating_preview#Show(l:lines) + else + call ale#preview#Show(l:lines, {'stay_here': l:stay_here}) + + " Clear the echo message if we manually displayed details. + if !l:stay_here + execute 'echo' + endif endif endfunction diff --git a/autoload/ale/dhall.vim b/autoload/ale/dhall.vim new file mode 100644 index 00000000..cc54418f --- /dev/null +++ b/autoload/ale/dhall.vim @@ -0,0 +1,24 @@ +" Author: Pat Brisbin <pbrisbin@gmail.com>, toastal <toastal@protonmail.com> +" Description: Functions for working with Dhall’s executable + +call ale#Set('dhall_executable', 'dhall') +call ale#Set('dhall_use_global', get(g:, 'ale_use_global_executables', 0)) +call ale#Set('dhall_options', '') + +function! ale#dhall#GetExecutable(buffer) abort + let l:executable = ale#Var(a:buffer, 'dhall_executable') + + " Dhall is written in Haskell and commonly installed with Stack + return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'dhall') +endfunction + +function! ale#dhall#GetExecutableWithOptions(buffer) abort + let l:executable = ale#dhall#GetExecutable(a:buffer) + + return l:executable + \ . ale#Pad(ale#Var(a:buffer, 'dhall_options')) +endfunction + +function! ale#dhall#GetCommand(buffer) abort + return '%e ' . ale#Pad(ale#Var(a:buffer, 'dhall_options')) +endfunction diff --git a/autoload/ale/fix/registry.vim b/autoload/ale/fix/registry.vim index 0f146faa..a591a57b 100644 --- a/autoload/ale/fix/registry.vim +++ b/autoload/ale/fix/registry.vim @@ -32,11 +32,37 @@ let s:default_registry = { \ 'suggested_filetypes': ['python'], \ 'description': 'Fix PEP8 issues with black.', \ }, +\ 'deno': { +\ 'function': 'ale#fixers#deno#Fix', +\ 'suggested_filetypes': ['typescript'], +\ 'description': 'Fix TypeScript using deno fmt.', +\ }, \ 'dfmt': { \ 'function': 'ale#fixers#dfmt#Fix', \ 'suggested_filetypes': ['d'], \ 'description': 'Fix D files with dfmt.', \ }, +\ 'dhall': { +\ 'function': 'ale#fixers#dhall#Fix', +\ 'suggested_filetypes': ['dhall'], +\ 'description': 'Fix Dhall files with dhall-format.', +\ }, +\ 'dhall-format': { +\ 'function': 'ale#fixers#dhall_format#Fix', +\ 'suggested_filetypes': ['dhall'], +\ 'description': 'Standard code formatter for the Dhall language', +\ 'aliases': ['dhall'], +\ }, +\ 'dhall-freeze': { +\ 'function': 'ale#fixers#dhall_freeze#Freeze', +\ 'suggested_filetypes': ['dhall'], +\ 'description': 'Add integrity checks to remote import statements of an expression for the Dhall language', +\ }, +\ 'dhall-lint': { +\ 'function': 'ale#fixers#dhall_lint#Fix', +\ 'suggested_filetypes': ['dhall'], +\ 'description': 'Standard code formatter for the Dhall language and removing dead code', +\ }, \ 'fecs': { \ 'function': 'ale#fixers#fecs#Fix', \ 'suggested_filetypes': ['javascript', 'css', 'html'], @@ -81,7 +107,7 @@ let s:default_registry = { \ }, \ 'prettier': { \ 'function': 'ale#fixers#prettier#Fix', -\ 'suggested_filetypes': ['javascript', 'typescript', 'css', 'less', 'scss', 'json', 'json5', 'graphql', 'markdown', 'vue', 'html', 'yaml'], +\ 'suggested_filetypes': ['javascript', 'typescript', 'css', 'less', 'scss', 'json', 'json5', 'graphql', 'markdown', 'vue', 'html', 'yaml', 'openapi'], \ 'description': 'Apply prettier to a file.', \ }, \ 'prettier_eslint': { @@ -132,7 +158,7 @@ let s:default_registry = { \ }, \ 'scalafmt': { \ 'function': 'ale#fixers#scalafmt#Fix', -\ 'suggested_filetypes': ['scala'], +\ 'suggested_filetypes': ['sbt', 'scala'], \ 'description': 'Fix Scala files using scalafmt', \ }, \ 'sorbet': { @@ -342,7 +368,7 @@ let s:default_registry = { \ }, \ 'ktlint': { \ 'function': 'ale#fixers#ktlint#Fix', -\ 'suggested_filetypes': ['kt'], +\ 'suggested_filetypes': ['kt', 'kotlin'], \ 'description': 'Fix Kotlin files with ktlint.', \ }, \ 'styler': { @@ -390,16 +416,11 @@ let s:default_registry = { \ 'suggested_filetypes': ['lua'], \ 'description': 'Fix Lua files with luafmt.', \ }, -\ 'dhall': { -\ 'function': 'ale#fixers#dhall#Fix', -\ 'suggested_filetypes': ['dhall'], -\ 'description': 'Fix Dhall files with dhall-format.', -\ }, \ 'ormolu': { \ 'function': 'ale#fixers#ormolu#Fix', \ 'suggested_filetypes': ['haskell'], \ 'description': 'A formatter for Haskell source code.', -\ }, +\ } \} " Reset the function registry to the default entries. diff --git a/autoload/ale/fixers/deno.vim b/autoload/ale/fixers/deno.vim new file mode 100644 index 00000000..7154c6ee --- /dev/null +++ b/autoload/ale/fixers/deno.vim @@ -0,0 +1,17 @@ +function! ale#fixers#deno#Fix(buffer) abort + let l:executable = ale#handlers#deno#GetExecutable(a:buffer) + + if !executable(l:executable) + return 0 + endif + + let l:options = ' fmt -' + + if ale#Var(a:buffer, 'deno_unstable') + let l:options = l:options . ' --unstable' + endif + + return { + \ 'command': ale#Escape(l:executable) . l:options + \} +endfunction diff --git a/autoload/ale/fixers/dhall.vim b/autoload/ale/fixers/dhall.vim deleted file mode 100644 index 18f6006c..00000000 --- a/autoload/ale/fixers/dhall.vim +++ /dev/null @@ -1,23 +0,0 @@ -" Author: Pat Brisbin <pbrisbin@gmail.com> -" Description: Integration of dhall-format with ALE. - -call ale#Set('dhall_format_executable', 'dhall') - -function! ale#fixers#dhall#GetExecutable(buffer) abort - let l:executable = ale#Var(a:buffer, 'dhall_format_executable') - - " Dhall is written in Haskell and commonly installed with Stack - return ale#handlers#haskell_stack#EscapeExecutable(l:executable, 'dhall') -endfunction - -function! ale#fixers#dhall#Fix(buffer) abort - let l:executable = ale#fixers#dhall#GetExecutable(a:buffer) - - return { - \ 'command': l:executable - \ . ' format' - \ . ' --inplace' - \ . ' %t', - \ 'read_temporary_file': 1, - \} -endfunction diff --git a/autoload/ale/fixers/dhall_format.vim b/autoload/ale/fixers/dhall_format.vim new file mode 100644 index 00000000..d4021983 --- /dev/null +++ b/autoload/ale/fixers/dhall_format.vim @@ -0,0 +1,14 @@ +" Author: toastal <toastal@protonmail.com> +" Description: Dhall’s built-in formatter +" +function! ale#fixers#dhall_format#Fix(buffer) abort + let l:executable = ale#dhall#GetExecutableWithOptions(a:buffer) + let l:command = l:executable + \ . ' format' + \ . ' --inplace %t' + + return { + \ 'command': l:command, + \ 'read_temporary_file': 1, + \} +endfunction diff --git a/autoload/ale/fixers/dhall_freeze.vim b/autoload/ale/fixers/dhall_freeze.vim new file mode 100644 index 00000000..74ae7530 --- /dev/null +++ b/autoload/ale/fixers/dhall_freeze.vim @@ -0,0 +1,18 @@ +" Author: toastal <toastal@protonmail.com> +" Description: Dhall’s package freezing + +call ale#Set('dhall_freeze_options', '') + +function! ale#fixers#dhall_freeze#Freeze(buffer) abort + let l:executable = ale#dhall#GetExecutableWithOptions(a:buffer) + let l:command = l:executable + \ . ' freeze' + \ . ale#Pad(ale#Var(a:buffer, 'dhall_freeze_options')) + \ . ' --inplace %t' + + + return { + \ 'command': l:command, + \ 'read_temporary_file': 1, + \} +endfunction diff --git a/autoload/ale/fixers/dhall_lint.vim b/autoload/ale/fixers/dhall_lint.vim new file mode 100644 index 00000000..2abbe6f7 --- /dev/null +++ b/autoload/ale/fixers/dhall_lint.vim @@ -0,0 +1,14 @@ +" Author: toastal <toastal@protonmail.com> +" Description: Dhall’s built-in linter/formatter + +function! ale#fixers#dhall_lint#Fix(buffer) abort + let l:executable = ale#dhall#GetExecutableWithOptions(a:buffer) + let l:command = l:executable + \ . ' lint' + \ . ' --inplace %t' + + return { + \ 'command': l:command, + \ 'read_temporary_file': 1, + \} +endfunction diff --git a/autoload/ale/fixers/isort.vim b/autoload/ale/fixers/isort.vim index 9070fb27..55bb550e 100644 --- a/autoload/ale/fixers/isort.vim +++ b/autoload/ale/fixers/isort.vim @@ -2,24 +2,35 @@ " Description: Fixing Python imports with isort. call ale#Set('python_isort_executable', 'isort') -call ale#Set('python_isort_options', '') call ale#Set('python_isort_use_global', get(g:, 'ale_use_global_executables', 0)) +call ale#Set('python_isort_options', '') +call ale#Set('python_isort_auto_pipenv', 0) + +function! ale#fixers#isort#GetExecutable(buffer) abort + if (ale#Var(a:buffer, 'python_auto_pipenv') || ale#Var(a:buffer, 'python_isort_auto_pipenv')) + \ && ale#python#PipenvPresent(a:buffer) + return 'pipenv' + endif + + return ale#python#FindExecutable(a:buffer, 'python_isort', ['isort']) +endfunction function! ale#fixers#isort#Fix(buffer) abort let l:options = ale#Var(a:buffer, 'python_isort_options') - let l:executable = ale#python#FindExecutable( - \ a:buffer, - \ 'python_isort', - \ ['isort'], - \) + let l:executable = ale#fixers#isort#GetExecutable(a:buffer) + + let l:exec_args = l:executable =~? 'pipenv$' + \ ? ' run isort' + \ : '' - if !executable(l:executable) + if !executable(l:executable) && l:executable isnot# 'pipenv' return 0 endif return { \ 'command': ale#path#BufferCdString(a:buffer) - \ . ale#Escape(l:executable) . (!empty(l:options) ? ' ' . l:options : '') . ' -', + \ . ale#Escape(l:executable) . l:exec_args + \ . (!empty(l:options) ? ' ' . l:options : '') . ' -', \} endfunction diff --git a/autoload/ale/fixers/prettier.vim b/autoload/ale/fixers/prettier.vim index e0f4972e..12c018af 100644 --- a/autoload/ale/fixers/prettier.vim +++ b/autoload/ale/fixers/prettier.vim @@ -83,6 +83,7 @@ function! ale#fixers#prettier#ApplyFixForVersion(buffer, version) abort \ 'markdown': 'markdown', \ 'vue': 'vue', \ 'yaml': 'yaml', + \ 'openapi': 'yaml', \ 'html': 'html', \} diff --git a/autoload/ale/fixers/standardrb.vim b/autoload/ale/fixers/standardrb.vim index 54330a37..acb310c6 100644 --- a/autoload/ale/fixers/standardrb.vim +++ b/autoload/ale/fixers/standardrb.vim @@ -12,12 +12,12 @@ function! ale#fixers#standardrb#GetCommand(buffer) abort return ale#ruby#EscapeExecutable(l:executable, 'standardrb') \ . (!empty(l:config) ? ' --config ' . ale#Escape(l:config) : '') \ . (!empty(l:options) ? ' ' . l:options : '') - \ . ' --fix --force-exclusion %t' + \ . ' --fix --force-exclusion --stdin %s' endfunction function! ale#fixers#standardrb#Fix(buffer) abort return { \ 'command': ale#fixers#standardrb#GetCommand(a:buffer), - \ 'read_temporary_file': 1, + \ 'process_with': 'ale#fixers#rubocop#PostProcess' \} endfunction diff --git a/autoload/ale/fixers/xo.vim b/autoload/ale/fixers/xo.vim index 882350be..dcf4c737 100644 --- a/autoload/ale/fixers/xo.vim +++ b/autoload/ale/fixers/xo.vim @@ -1,23 +1,36 @@ " Author: Albert Marquez - https://github.com/a-marquez " Description: Fixing files with XO. -call ale#Set('javascript_xo_executable', 'xo') -call ale#Set('javascript_xo_use_global', get(g:, 'ale_use_global_executables', 0)) -call ale#Set('javascript_xo_options', '') +function! ale#fixers#xo#Fix(buffer) abort + let l:executable = ale#handlers#xo#GetExecutable(a:buffer) + let l:options = ale#handlers#xo#GetOptions(a:buffer) -function! ale#fixers#xo#GetExecutable(buffer) abort - return ale#node#FindExecutable(a:buffer, 'javascript_xo', [ - \ 'node_modules/xo/cli.js', - \ 'node_modules/.bin/xo', - \]) + return ale#semver#RunWithVersionCheck( + \ a:buffer, + \ l:executable, + \ '%e --version', + \ {b, v -> ale#fixers#xo#ApplyFixForVersion(b, v, l:executable, l:options)} + \) endfunction -function! ale#fixers#xo#Fix(buffer) abort - let l:executable = ale#fixers#xo#GetExecutable(a:buffer) +function! ale#fixers#xo#ApplyFixForVersion(buffer, version, executable, options) abort + let l:executable = ale#node#Executable(a:buffer, a:executable) + let l:options = ale#Pad(a:options) + + " 0.30.0 is the first version with a working --stdin --fix + if ale#semver#GTE(a:version, [0, 30, 0]) + return { + \ 'command': l:executable + \ . ' --stdin --stdin-filename %s' + \ . ' --fix' + \ . l:options, + \} + endif return { - \ 'command': ale#node#Executable(a:buffer, l:executable) - \ . ' --fix %t', + \ 'command': l:executable + \ . ' --fix %t' + \ . l:options, \ 'read_temporary_file': 1, \} endfunction diff --git a/autoload/ale/floating_preview.vim b/autoload/ale/floating_preview.vim new file mode 100644 index 00000000..e6a75689 --- /dev/null +++ b/autoload/ale/floating_preview.vim @@ -0,0 +1,91 @@ +" Author: Jan-Grimo Sobez <jan-grimo.sobez@phys.chem.ethz.ch> +" Author: Kevin Clark <kevin.clark@gmail.com> +" Description: Floating preview window for showing whatever information in. + +" Precondition: exists('*nvim_open_win') + +function! ale#floating_preview#Show(lines, ...) abort + if !exists('*nvim_open_win') + execute 'echom ''Floating windows not supported in this vim instance.''' + + return + endif + + " Remove the close autocmd so it doesn't happen mid update + augroup ale_floating_preview_window + autocmd! + augroup END + + let l:options = get(a:000, 0, {}) + + " Only create a new window if we need it + if !exists('w:preview') || index(nvim_list_wins(), w:preview['id']) is# -1 + call s:Create(l:options) + else + call nvim_buf_set_option(w:preview['buffer'], 'modifiable', v:true) + endif + + " Execute commands in window context + let l:parent_window = nvim_get_current_win() + + call nvim_set_current_win(w:preview['id']) + + for l:command in get(l:options, 'commands', []) + call execute(l:command) + endfor + + call nvim_set_current_win(l:parent_window) + + " Return to parent context on move + augroup ale_floating_preview_window + autocmd! + + if g:ale_close_preview_on_insert + autocmd CursorMoved,TabLeave,WinLeave,InsertEnter <buffer> ++once call s:Close() + else + autocmd CursorMoved,TabLeave,WinLeave <buffer> ++once call s:Close() + endif + augroup END + + let l:width = max(map(copy(a:lines), 'strdisplaywidth(v:val)')) + let l:height = min([len(a:lines), 10]) + call nvim_win_set_width(w:preview['id'], l:width) + call nvim_win_set_height(w:preview['id'], l:height) + + call nvim_buf_set_lines(w:preview['buffer'], 0, -1, v:false, a:lines) + call nvim_buf_set_option(w:preview['buffer'], 'modified', v:false) + call nvim_buf_set_option(w:preview['buffer'], 'modifiable', v:false) +endfunction + +function! s:Create(options) abort + let l:buffer = nvim_create_buf(v:false, v:false) + let l:winid = nvim_open_win(l:buffer, v:false, { + \ 'relative': 'cursor', + \ 'row': 1, + \ 'col': 0, + \ 'width': 42, + \ 'height': 4, + \ 'style': 'minimal' + \ }) + call nvim_buf_set_option(l:buffer, 'buftype', 'acwrite') + call nvim_buf_set_option(l:buffer, 'bufhidden', 'delete') + call nvim_buf_set_option(l:buffer, 'swapfile', v:false) + call nvim_buf_set_option(l:buffer, 'filetype', get(a:options, 'filetype', 'ale-preview')) + + let w:preview = {'id': l:winid, 'buffer': l:buffer} +endfunction + +function! s:Close() abort + if !exists('w:preview') + return + endif + + call setbufvar(w:preview['buffer'], '&modified', 0) + + if win_id2win(w:preview['id']) > 0 + execute win_id2win(w:preview['id']).'wincmd c' + endif + + unlet w:preview +endfunction + diff --git a/autoload/ale/handlers/atools.vim b/autoload/ale/handlers/atools.vim new file mode 100644 index 00000000..c273fc40 --- /dev/null +++ b/autoload/ale/handlers/atools.vim @@ -0,0 +1,41 @@ +" Author: Leo <thinkabit.ukim@gmail.com> +" Description: Handlers for output expected from atools + +function! ale#handlers#atools#Handle(buffer, lines) abort + " Format: SEVERITY:[TAG]:PATH:LINENUM:MSG + " Example: MC:[AL5]:./APKBUILD:12:variable set to empty string: install= + let l:pattern = '\([^:]\+\):\([^:]\+\):\([^:]\+\):\(\d\+\):\(.\+\)$' + let l:output = [] + + for l:match in ale#util#GetMatches(a:lines, l:pattern) + " We are expected to receive 2 characters, the first character + " can be 'S', 'I', 'M' 'T', which are respectively: + " Serious (Error) + " Important (Error) + " Minor (Warning) + " Style (Warning) + " + " The second character can be either 'C' or 'P', which are respectively: + " Certain (Error) + " Possible (Warning) + let l:severity = matchstr(l:match[1], '^.') + let l:certainty = matchstr(l:match[1], '.$') + + let l:type = 'E' + " If the tag returns 'Minor' or 'Style' or is 'Possible' + " then return a warning + + if l:severity is# 'M' || l:severity is# 'T' || l:certainty is# 'P' + let l:type = 'W' + endif + + call add(l:output, { + \ 'lnum': l:match[4] + 0, + \ 'text': l:match[5], + \ 'type': l:type, + \ 'code': matchstr(l:match[2], 'AL[0-9]*'), + \}) + endfor + + return l:output +endfunction diff --git a/autoload/ale/handlers/deno.vim b/autoload/ale/handlers/deno.vim new file mode 100644 index 00000000..4bf4546a --- /dev/null +++ b/autoload/ale/handlers/deno.vim @@ -0,0 +1,52 @@ +" Author: Mohammed Chelouti - https://github.com/motato1 +" Description: Handler functions for Deno. + +call ale#Set('deno_executable', 'deno') +call ale#Set('deno_unstable', 0) +call ale#Set('deno_lsp_project_root', '') + +function! ale#handlers#deno#GetExecutable(buffer) abort + return ale#Var(a:buffer, 'deno_executable') +endfunction + +" Find project root for Deno's language server. +" +" Deno projects do not require a project or configuration file at the project root. +" This means the root directory has to be guessed, +" unless it is explicitly specified by the user. +" +" The project root is determined by ... +" 1. using a user-specified value from deno_lsp_project_root +" 2. looking for common top-level files/dirs +" 3. using the buffer's directory +function! ale#handlers#deno#GetProjectRoot(buffer) abort + let l:project_root = ale#Var(a:buffer, 'deno_lsp_project_root') + + if !empty(l:project_root) + return l:project_root + endif + + let l:possible_project_roots = [ + \ 'tsconfig.json', + \ '.git', + \ bufname(a:buffer), + \] + + for l:possible_root in l:possible_project_roots + let l:project_root = ale#path#FindNearestFile(a:buffer, l:possible_root) + + if empty(l:project_root) + let l:project_root = ale#path#FindNearestDirectory(a:buffer, l:possible_root) + endif + + if !empty(l:project_root) + " dir:p expands to /full/path/to/dir/ whereas + " file:p expands to /full/path/to/file (no trailing slash) + " Appending '/' ensures that :h:h removes the path's last segment + " regardless of whether it is a directory or not. + return fnamemodify(l:project_root . '/', ':p:h:h') + endif + endfor + + return '' +endfunction diff --git a/autoload/ale/handlers/hdl_checker.vim b/autoload/ale/handlers/hdl_checker.vim index 36dbd259..e11c5377 100644 --- a/autoload/ale/handlers/hdl_checker.vim +++ b/autoload/ale/handlers/hdl_checker.vim @@ -32,6 +32,8 @@ function! ale#handlers#hdl_checker#GetProjectRoot(buffer) abort if ale#handlers#hdl_checker#IsDotGit(l:project_root) return fnamemodify(l:project_root, ':h:h') endif + + return '' endfunction function! ale#handlers#hdl_checker#GetExecutable(buffer) abort diff --git a/autoload/ale/handlers/inko.vim b/autoload/ale/handlers/inko.vim new file mode 100644 index 00000000..73f06871 --- /dev/null +++ b/autoload/ale/handlers/inko.vim @@ -0,0 +1,37 @@ +" Author: Yorick Peterse <yorick@yorickpeterse.com> +" Description: output handlers for the Inko JSON format + +function! ale#handlers#inko#GetType(severity) abort + if a:severity is? 'warning' + return 'W' + endif + + return 'E' +endfunction + +function! ale#handlers#inko#Handle(buffer, lines) abort + try + let l:errors = json_decode(join(a:lines, '')) + catch + return [] + endtry + + if empty(l:errors) + return [] + endif + + let l:output = [] + let l:dir = expand('#' . a:buffer . ':p:h') + + for l:error in l:errors + call add(l:output, { + \ 'filename': ale#path#GetAbsPath(l:dir, l:error['file']), + \ 'lnum': l:error['line'], + \ 'col': l:error['column'], + \ 'text': l:error['message'], + \ 'type': ale#handlers#inko#GetType(l:error['level']), + \}) + endfor + + return l:output +endfunction diff --git a/autoload/ale/handlers/spectral.vim b/autoload/ale/handlers/spectral.vim new file mode 100644 index 00000000..1eb4a5de --- /dev/null +++ b/autoload/ale/handlers/spectral.vim @@ -0,0 +1,31 @@ +" Author: t2h5 <https://github.com/t2h5> +" Description: Integration of Stoplight Spectral CLI with ALE. + +function! ale#handlers#spectral#HandleSpectralOutput(buffer, lines) abort + " Matches patterns like the following: + " openapi.yml:1:1 error oas3-schema "Object should have required property `info`." + " openapi.yml:1:1 warning oas3-api-servers "OpenAPI `servers` must be present and non-empty array." + let l:pattern = '\v^.*:(\d+):(\d+) (error|warning) (.*)$' + let l:output = [] + + for l:match in ale#util#GetMatches(a:lines, l:pattern) + let l:obj = { + \ 'lnum': l:match[1] + 0, + \ 'col': l:match[2] + 0, + \ 'type': l:match[3] is# 'error' ? 'E' : 'W', + \ 'text': l:match[4], + \} + + let l:code_match = matchlist(l:obj.text, '\v^(.+) "(.+)"$') + + if !empty(l:code_match) + let l:obj.code = l:code_match[1] + let l:obj.text = l:code_match[2] + endif + + call add(l:output, l:obj) + endfor + + return l:output +endfunction + diff --git a/autoload/ale/handlers/xo.vim b/autoload/ale/handlers/xo.vim new file mode 100644 index 00000000..c63278c0 --- /dev/null +++ b/autoload/ale/handlers/xo.vim @@ -0,0 +1,44 @@ +call ale#Set('javascript_xo_executable', 'xo') +call ale#Set('javascript_xo_use_global', get(g:, 'ale_use_global_executables', 0)) +call ale#Set('javascript_xo_options', '') + +call ale#Set('typescript_xo_executable', 'xo') +call ale#Set('typescript_xo_use_global', get(g:, 'ale_use_global_executables', 0)) +call ale#Set('typescript_xo_options', '') + +function! ale#handlers#xo#GetExecutable(buffer) abort + let l:type = ale#handlers#xo#GetType(a:buffer) + + return ale#node#FindExecutable(a:buffer, l:type . '_xo', [ + \ 'node_modules/xo/cli.js', + \ 'node_modules/.bin/xo', + \]) +endfunction + +function! ale#handlers#xo#GetLintCommand(buffer) abort + return ale#Escape(ale#handlers#xo#GetExecutable(a:buffer)) + \ . ale#Pad(ale#handlers#xo#GetOptions(a:buffer)) + \ . ' --reporter json --stdin --stdin-filename %s' +endfunction + +function! ale#handlers#xo#GetOptions(buffer) abort + let l:type = ale#handlers#xo#GetType(a:buffer) + + return ale#Var(a:buffer, l:type . '_xo_options') +endfunction + +" xo uses eslint and the output format is the same +function! ale#handlers#xo#HandleJSON(buffer, lines) abort + return ale#handlers#eslint#HandleJSON(a:buffer, a:lines) +endfunction + +function! ale#handlers#xo#GetType(buffer) abort + let l:filetype = getbufvar(a:buffer, '&filetype') + let l:type = 'javascript' + + if l:filetype =~# 'typescript' + let l:type = 'typescript' + endif + + return l:type +endfunction diff --git a/autoload/ale/handlers/yamllint.vim b/autoload/ale/handlers/yamllint.vim new file mode 100644 index 00000000..5e04577d --- /dev/null +++ b/autoload/ale/handlers/yamllint.vim @@ -0,0 +1,39 @@ +function! ale#handlers#yamllint#GetCommand(buffer) abort + return '%e' . ale#Pad(ale#Var(a:buffer, 'yaml_yamllint_options')) + \ . ' -f parsable %t' +endfunction + +function! ale#handlers#yamllint#Handle(buffer, lines) abort + " Matches patterns line the following: + " something.yaml:1:1: [warning] missing document start "---" (document-start) + " something.yml:2:1: [error] syntax error: expected the node content, but found '<stream end>' + let l:pattern = '\v^.*:(\d+):(\d+): \[(error|warning)\] (.+)$' + let l:output = [] + + for l:match in ale#util#GetMatches(a:lines, l:pattern) + let l:item = { + \ 'lnum': l:match[1] + 0, + \ 'col': l:match[2] + 0, + \ 'text': l:match[4], + \ 'type': l:match[3] is# 'error' ? 'E' : 'W', + \} + + let l:code_match = matchlist(l:item.text, '\v^(.+) \(([^)]+)\)$') + + if !empty(l:code_match) + if l:code_match[2] is# 'trailing-spaces' + \&& !ale#Var(a:buffer, 'warn_about_trailing_whitespace') + " Skip warnings for trailing whitespace if the option is off. + continue + endif + + let l:item.text = l:code_match[1] + let l:item.code = l:code_match[2] + endif + + call add(l:output, l:item) + endfor + + return l:output +endfunction + diff --git a/autoload/ale/hover.vim b/autoload/ale/hover.vim index 1d38f3b9..cb0379fd 100644 --- a/autoload/ale/hover.vim +++ b/autoload/ale/hover.vim @@ -46,6 +46,10 @@ function! ale#hover#HandleTSServerResponse(conn_id, response) abort call balloon_show(a:response.body.displayString) elseif get(l:options, 'truncated_echo', 0) call ale#cursor#TruncatedEcho(split(a:response.body.displayString, "\n")[0]) + elseif g:ale_hover_to_floating_preview || g:ale_floating_preview + call ale#floating_preview#Show(split(a:response.body.displayString, "\n"), { + \ 'filetype': 'ale-preview.message', + \}) elseif g:ale_hover_to_preview call ale#preview#Show(split(a:response.body.displayString, "\n"), { \ 'filetype': 'ale-preview.message', @@ -226,6 +230,11 @@ function! ale#hover#HandleLSPResponse(conn_id, response) abort call balloon_show(join(l:lines, "\n")) elseif get(l:options, 'truncated_echo', 0) call ale#cursor#TruncatedEcho(l:lines[0]) + elseif g:ale_hover_to_floating_preview || g:ale_floating_preview + call ale#floating_preview#Show(l:lines, { + \ 'filetype': 'ale-preview.message', + \ 'commands': l:commands, + \}) elseif g:ale_hover_to_preview call ale#preview#Show(l:lines, { \ 'filetype': 'ale-preview.message', diff --git a/autoload/ale/linter.vim b/autoload/ale/linter.vim index 645c25f9..f9ec48d7 100644 --- a/autoload/ale/linter.vim +++ b/autoload/ale/linter.vim @@ -38,11 +38,13 @@ let s:default_ale_linter_aliases = { " " NOTE: Update the g:ale_linters documentation when modifying this. let s:default_ale_linters = { +\ 'apkbuild': ['apkbuild_lint', 'secfixes_check'], \ 'csh': ['shell'], \ 'elixir': ['credo', 'dialyxir', 'dogma'], \ 'go': ['gofmt', 'golint', 'go vet'], \ 'hack': ['hack'], \ 'help': [], +\ 'inko': ['inko'], \ 'perl': ['perlcritic'], \ 'perl6': [], \ 'python': ['flake8', 'mypy', 'pylint', 'pyright'], diff --git a/autoload/ale/list.vim b/autoload/ale/list.vim index 4bfe2a7b..c2ae5cc5 100644 --- a/autoload/ale/list.vim +++ b/autoload/ale/list.vim @@ -20,11 +20,17 @@ endif " Return 1 if there is a buffer with buftype == 'quickfix' in bufffer list function! ale#list#IsQuickfixOpen() abort - for l:buf in range(1, bufnr('$')) - if getbufvar(l:buf, '&buftype') is# 'quickfix' - return 1 - endif - endfor + let l:res = getqflist({ 'winid' : winnr() }) + + if has_key(l:res, 'winid') && l:res.winid > 0 + return 1 + endif + + let l:res = getloclist(0, { 'winid' : winnr() }) + + if has_key(l:res, 'winid') && l:res.winid > 0 + return 1 + endif return 0 endfunction diff --git a/autoload/ale/lsp_linter.vim b/autoload/ale/lsp_linter.vim index dcd76e8f..628dde78 100644 --- a/autoload/ale/lsp_linter.vim +++ b/autoload/ale/lsp_linter.vim @@ -85,12 +85,18 @@ function! s:HandleTSServerDiagnostics(response, error_type) abort endif let l:info.syntax_loclist = l:thislist - else + elseif a:error_type is# 'semantic' if len(l:thislist) is 0 && len(get(l:info, 'semantic_loclist', [])) is 0 let l:no_changes = 1 endif let l:info.semantic_loclist = l:thislist + else + if len(l:thislist) is 0 && len(get(l:info, 'suggestion_loclist', [])) is 0 + let l:no_changes = 1 + endif + + let l:info.suggestion_loclist = l:thislist endif if l:no_changes @@ -98,6 +104,7 @@ function! s:HandleTSServerDiagnostics(response, error_type) abort endif let l:loclist = get(l:info, 'semantic_loclist', []) + \ + get(l:info, 'suggestion_loclist', []) \ + get(l:info, 'syntax_loclist', []) call ale#engine#HandleLoclist(l:linter_name, l:buffer, l:loclist, 0) @@ -150,6 +157,10 @@ function! ale#lsp_linter#HandleLSPResponse(conn_id, response) abort elseif get(a:response, 'type', '') is# 'event' \&& get(a:response, 'event', '') is# 'syntaxDiag' call s:HandleTSServerDiagnostics(a:response, 'syntax') + elseif get(a:response, 'type', '') is# 'event' + \&& get(a:response, 'event', '') is# 'suggestionDiag' + \&& get(g:, 'ale_lsp_suggestions', '1') == 1 + call s:HandleTSServerDiagnostics(a:response, 'suggestion') endif endfunction diff --git a/autoload/ale/maven.vim b/autoload/ale/maven.vim index 745f8c93..42735286 100644 --- a/autoload/ale/maven.vim +++ b/autoload/ale/maven.vim @@ -25,7 +25,7 @@ function! ale#maven#FindExecutable(buffer) abort let l:wrapper_cmd = has('unix') ? 'mvnw' : 'mvnw.cmd' let l:wrapper_path = ale#path#FindNearestFile(a:buffer, l:wrapper_cmd) - if executable(l:wrapper_path) + if !empty(l:wrapper_path) && executable(l:wrapper_path) return l:wrapper_path endif diff --git a/autoload/ale/python.vim b/autoload/ale/python.vim index 7ed22367..fc6c1130 100644 --- a/autoload/ale/python.vim +++ b/autoload/ale/python.vim @@ -32,6 +32,8 @@ function! ale#python#FindProjectRootIni(buffer) abort \|| filereadable(l:path . '/.pylintrc') \|| filereadable(l:path . '/Pipfile') \|| filereadable(l:path . '/Pipfile.lock') + \|| filereadable(l:path . '/poetry.lock') + \|| filereadable(l:path . '/pyproject.toml') return l:path endif endfor diff --git a/autoload/ale/sign.vim b/autoload/ale/sign.vim index 8109c60e..2864f39b 100644 --- a/autoload/ale/sign.vim +++ b/autoload/ale/sign.vim @@ -50,9 +50,12 @@ if !hlexists('ALESignColumnWithErrors') endif function! ale#sign#SetUpDefaultColumnWithoutErrorsHighlight() abort + let l:verbose = &verbose + set verbose=0 redir => l:output 0verbose silent highlight SignColumn redir end + let &verbose = l:verbose let l:highlight_syntax = join(split(l:output)[2:]) let l:match = matchlist(l:highlight_syntax, '\vlinks to (.+)$') diff --git a/autoload/ale/socket.vim b/autoload/ale/socket.vim index 7e069fb5..61f11e70 100644 --- a/autoload/ale/socket.vim +++ b/autoload/ale/socket.vim @@ -72,9 +72,8 @@ function! ale#socket#Open(address, options) abort elseif exists('*chansend') && exists('*sockconnect') " NeoVim 0.3+ try - let l:channel_id = sockconnect('tcp', a:address, { - \ 'on_data': function('s:NeoVimOutputCallback'), - \}) + let l:channel_id = sockconnect(stridx(a:address, ':') != -1 ? 'tcp' : 'pipe', + \ a:address, {'on_data': function('s:NeoVimOutputCallback')}) let l:channel_info.last_line = '' catch /connection failed/ let l:channel_id = -1 diff --git a/autoload/ale/util.vim b/autoload/ale/util.vim index fcc03eb7..5c41ab83 100644 --- a/autoload/ale/util.vim +++ b/autoload/ale/util.vim @@ -409,7 +409,7 @@ function! ale#util#FuzzyJSONDecode(data, default) abort endif return l:result - catch /E474/ + catch /E474\|E491/ return a:default endtry endfunction @@ -486,7 +486,7 @@ function! ale#util#Input(message, value) abort endfunction function! ale#util#HasBuflineApi() abort - return exists('*deletebufline') && exists('*appendbufline') && exists('*getpos') && exists('*setpos') + return exists('*deletebufline') && exists('*setbufline') endfunction " Sets buffer contents to lines @@ -507,11 +507,8 @@ function! ale#util#SetBufferContents(buffer, lines) abort " Use a Vim API for setting lines in other buffers, if available. if l:has_bufline_api - let l:save_cursor = getpos('.') - call deletebufline(a:buffer, 1, '$') - call appendbufline(a:buffer, 1, l:new_lines) - call deletebufline(a:buffer, 1, 1) - call setpos('.', l:save_cursor) + call setbufline(a:buffer, 1, l:new_lines) + call deletebufline(a:buffer, l:first_line_to_remove, '$') " Fall back on setting lines the old way, for the current buffer. else let l:old_line_length = line('$') diff --git a/doc/ale-ada.txt b/doc/ale-ada.txt index 2ac30c0a..0fc55a9c 100644 --- a/doc/ale-ada.txt +++ b/doc/ale-ada.txt @@ -33,4 +33,34 @@ g:ale_ada_gnatpp_options *g:ale_ada_gnatpp_options* =============================================================================== +ada-language-server *ale-ada-language-server* + +g:ale_ada_adals_executable *g:ale_ada_adals_executable* + *b:ale_ada_adals_executable* + Type: |String| + Default: `'ada_language_server'` + + This variable can be changed to use a different executable for Ada Language + Server. + + +g:ale_ada_adals_project *g:ale_ada_adals_project* + *b:ale_ada_adals_project* + Type: |String| + Default: `'default.gpr'` + +This variable can be changed to use a different GPR file for +Ada Language Server. + + +g:ale_ada_adals_encoding *g:ale_ada_adals_encoding* + *b:ale_ada_adals_encoding* + Type: |String| + Default: `'utf-8'` + +This variable can be changed to use a different file encoding for +Ada Language Server. + + +=============================================================================== vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale-apkbuild.txt b/doc/ale-apkbuild.txt new file mode 100644 index 00000000..05261400 --- /dev/null +++ b/doc/ale-apkbuild.txt @@ -0,0 +1,30 @@ +=============================================================================== +ALE APKBUILD Integration *ale-apkbuild-options* + + +=============================================================================== +apkbuild-lint *ale-apkbuild-apkbuild-lint* + +g:ale_apkbuild_apkbuild_lint_executable + *g:ale_apkbuild_apkbuild_lint_executable* + *b:ale_apkbuild_apkbuild_lint_executable* + + Type: |String| + Default: `'apkbuild-lint'` + + This variable can be set to change the path to apkbuild-lint + +=============================================================================== +secfixes-check *ale-apkbuild-secfixes-check* + +g:ale_apkbuild_secfixes_check_executable + *g:ale_apkbuild_secfixes_check_executable* + *b:ale_apkbuild_secfixes_check_executable* + + Type: |String| + Default: `'secfixes-check'` + + This variable can be set to change the path to secfixes-check + +=============================================================================== + vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale-dafny.txt b/doc/ale-dafny.txt new file mode 100644 index 00000000..005170ad --- /dev/null +++ b/doc/ale-dafny.txt @@ -0,0 +1,16 @@ +=============================================================================== +ALE Dafny Integration *ale-dafny-options* + + +=============================================================================== +dafny *ale-dafny-dafny* + +g:ale_dafny_dafny_timelimit *g:ale_dafny_dafny_timelimit* + *b:ale_dafny_dafny_timelimit* + Type: |Number| + Default: `10` + + This variable sets the `/timeLimit` used for dafny. + + + vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale-dart.txt b/doc/ale-dart.txt index a6d88dd8..01089252 100644 --- a/doc/ale-dart.txt +++ b/doc/ale-dart.txt @@ -3,6 +3,31 @@ ALE Dart Integration *ale-dart-options* =============================================================================== +analysis_server *ale-dart-analysis_server* + +Installation +------------------------------------------------------------------------------- + +Install Dart via whatever means. `analysis_server` will be included in the SDK. + +In case that `dart` is not in your path, try to set the executable option to +its absolute path. : > + " Set the executable path for dart to the absolute path to it. + let g:ale_dart_analysis_server_executable = '/usr/local/bin/dart' +< + +Options +------------------------------------------------------------------------------- + +g:ale_dart_analysis_server_executable *g:ale_dart_analysis_server_executable* + *b:ale_dart_analysis_server_executable* + Type: |String| + Default: `'dart'` + + This variable can be set to change the path of dart. + + +=============================================================================== dartanalyzer *ale-dart-dartanalyzer* Installation diff --git a/doc/ale-development.txt b/doc/ale-development.txt index afd9798f..dbbeb2da 100644 --- a/doc/ale-development.txt +++ b/doc/ale-development.txt @@ -148,13 +148,14 @@ Apply the following rules when writing Bash scripts. =============================================================================== 4. Testing ALE *ale-development-tests* *ale-dev-tests* *ale-tests* -ALE is tested with a suite of tests executed in Travis CI and AppVeyor. ALE -runs tests with the following versions of Vim in the following environments. - -1. Vim 8.0.0027 on Linux via Travis CI. -2. Vim 8.1.0519 on Linux via Travis CI. -3. NeoVim 0.2.0 on Linux via Travis CI. -4. NeoVim 0.3.5 on Linux via Travis CI. +ALE is tested with a suite of tests executed via GitHub Actions and AppVeyor. +ALE runs tests with the following versions of Vim in the following +environments. + +1. Vim 8.0.0027 on Linux via GitHub Actions. +2. Vim 8.2.2401 on Linux via GitHub Actions. +3. NeoVim 0.2.0 on Linux via GitHub Actions. +4. NeoVim 0.4.4 on Linux via GitHub Actions. 5. Vim 8 (stable builds) on Windows via AppVeyor. If you are developing ALE code on Linux, Mac OSX, or BSD, you can run ALEs @@ -192,7 +193,8 @@ tests. When you add new linters or fixers, make sure to add them into the tables in supported-tools.md and |ale-supported-languages-and-tools.txt|. If you forget to -keep them both in sync, you should see an error like the following in Travis CI. +keep them both in sync, you should see an error like the following in the +builds run for GitHub Actions. > ======================================== diff supported-tools.md and doc/ale-supported-languages-and-tools.txt tables diff --git a/doc/ale-dhall.txt b/doc/ale-dhall.txt new file mode 100644 index 00000000..44b0bf32 --- /dev/null +++ b/doc/ale-dhall.txt @@ -0,0 +1,52 @@ +=============================================================================== +ALE Dhall Integration *ale-dhall-options* + +g:ale_dhall_executable *g:ale_dhall_executable* + *b:ale_dhall_executable* + Type: |String| + Default: `'dhall'` + +g:ale_dhall_options g:ale_dhall_options + b:ale_dhall_options + Type: |String| + Default: `''` + + This variable can be set to pass additional options to the 'dhall` executable. + This is shared with `dhall-freeze` and `dhall-lint`. +> + let g:dhall_options = '--ascii' +< + +=============================================================================== +dhall-format *ale-dhall-format* + +Dhall + (https://dhall-lang.org/) + + +=============================================================================== +dhall-freeze *ale-dhall-freeze* + +Dhall + (https://dhall-lang.org/) + +g:ale_dhall_freeze_options g:ale_dhall_freeze_options + b:ale_dhall_freeze_options + Type: |String| + Default: `''` + + This variable can be set to pass additional options to the 'dhall freeze` + executable. +> + let g:dhall_freeze_options = '--all' +< + +=============================================================================== +dhall-lint *ale-dhall-lint* + +Dhall + (https://dhall-lang.org/) + + +=============================================================================== + vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale-elixir.txt b/doc/ale-elixir.txt index de9daacf..a4e5c2c6 100644 --- a/doc/ale-elixir.txt +++ b/doc/ale-elixir.txt @@ -85,5 +85,12 @@ g:ale_elixir_credo_strict *g:ale_elixir_credo_strict* Tells credo to run in strict mode or suggest mode. Set variable to 1 to enable --strict mode. +g:ale_elixir_credo_config_file g:ale_elixir_credo_config_file + + Type: String + Default: '' + + Tells credo to use a custom configuration file. + =============================================================================== vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale-erlang.txt b/doc/ale-erlang.txt index 38762f08..93ac7915 100644 --- a/doc/ale-erlang.txt +++ b/doc/ale-erlang.txt @@ -13,6 +13,14 @@ g:ale_erlang_dialyzer_executable *g:ale_erlang_dialyzer_executable* This variable can be changed to specify the dialyzer executable. +g:ale_erlang_dialyzer_options *g:ale_erlang_dialyzer_options* + *b:ale_erlang_dialyzer_options* + Type: |String| + Default: `'-Wunmatched_returns -Werror_handling -Wrace_conditions -Wunderspec'` + + This variable can be changed to specify the options to pass to the dialyzer + executable. + g:ale_erlang_dialyzer_plt_file *g:ale_erlang_dialyzer_plt_file* *b:ale_erlang_dialyzer_plt_file* Type: |String| @@ -46,6 +54,14 @@ g:ale_erlang_elvis_executable *g:ale_erlang_elvis_executable* ------------------------------------------------------------------------------- erlc *ale-erlang-erlc* +g:ale_erlang_erlc_executable *g:ale_erlang_erlc_executable* + *b:ale_erlang_erlc_executable* + Type: |String| + Default: `'erlc'` + + This variable can be changed to specify the erlc executable. + + g:ale_erlang_erlc_options *g:ale_erlang_erlc_options* *b:ale_erlang_erlc_options* Type: |String| diff --git a/doc/ale-haskell.txt b/doc/ale-haskell.txt index fde439fe..09894340 100644 --- a/doc/ale-haskell.txt +++ b/doc/ale-haskell.txt @@ -125,6 +125,18 @@ g:ale_haskell_hlint_options g:ale_haskell_hlint_options =============================================================================== +hls *ale-haskell-hls* + +g:ale_haskell_hls_executable *g:ale_haskell_hls_executable* + *b:ale_haskell_his_executable* + Type: |String| + Default: `'haskell-language-server-wrapper'` + + This variable can be changed to use a different executable for the haskell + language server. + + +=============================================================================== stack-build *ale-haskell-stack-build* g:ale_haskell_stack_build_options *g:ale_haskell_stack_build_options* diff --git a/doc/ale-inko.txt b/doc/ale-inko.txt new file mode 100644 index 00000000..5ca14af6 --- /dev/null +++ b/doc/ale-inko.txt @@ -0,0 +1,22 @@ +=============================================================================== +ALE Inko Integration *ale-inko-options* + *ale-integration-inko* + +=============================================================================== +Integration Information + + Currently, the only supported linter for Inko is the Inko compiler itself. + +=============================================================================== +inko *ale-inko-inko* + +g:ale_inko_inko_executable *g:ale_inko_inko_executable* + *b:ale_inko_inko_executable* + Type: |String| + Default: `'inko'` + + This variable can be modified to change the executable path for `inko`. + + +=============================================================================== + vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale-json.txt b/doc/ale-json.txt index 96499a04..dc91e14c 100644 --- a/doc/ale-json.txt +++ b/doc/ale-json.txt @@ -102,4 +102,36 @@ See |ale-javascript-prettier| for information about the available options. =============================================================================== +spectral *ale-json-spectral* + +Website: https://github.com/stoplightio/spectral + +Installation +------------------------------------------------------------------------------- + +Install spectral either globally or locally: > + + npm install @stoplight/spectral -g # global + npm install @stoplight/spectral # local +< + +Options +------------------------------------------------------------------------------- + +g:ale_json_spectral_executable *g:ale_json_spectral_executable* + *b:ale_json_spectral_executable* + Type: |String| + Default: `'spectral'` + + This variable can be set to change the path to spectral. + +g:ale_json_spectral_use_global *g:ale_json_spectral_use_global* + *b:ale_json_spectral_use_global* + Type: |String| + Default: `get(g:, 'ale_use_global_executables', 0)` + + See |ale-integrations-local-executables| + + +=============================================================================== vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale-openapi.txt b/doc/ale-openapi.txt new file mode 100644 index 00000000..1fc41add --- /dev/null +++ b/doc/ale-openapi.txt @@ -0,0 +1,74 @@ +=============================================================================== +ALE OpenApi Integration *ale-openapi-options* + +=============================================================================== +ibm_validator *ale-openapi-ibm-validator* + +Website: https://github.com/IBM/openapi-validator + + +Installation +------------------------------------------------------------------------------- + +Install ibm-openapi-validator either globally or locally: > + + npm install ibm-openapi-validator -g # global + npm install ibm-openapi-validator # local +< +Configuration +------------------------------------------------------------------------------- + +OpenAPI files can be written in YAML or JSON so in order for ALE plugins to +work with these files we must set the buffer |filetype| to either |openapi.yaml| +or |openapi.json| respectively. This causes ALE to lint the file with linters +configured for openapi and yaml files or openapi and json files respectively. + +For example setting filetype to |openapi.yaml| on a buffer and the following +|g:ale_linters| configuration will enable linting of openapi files using both +|ibm_validator| and |yamlint|: + +> + let g:ale_linters = { + \ 'yaml': ['yamllint'], + \ 'openapi': ['ibm_validator'] + \} +< + +The following plugin will detect openapi files automatically and set the +filetype to |openapi.yaml| or |openapi.json|: + + https://github.com/hsanson/vim-openapi + +Options +------------------------------------------------------------------------------- + +g:ale_openapi_ibm_validator_executable *g:ale_openapi_ibm_validator_executable* + *b:ale_openapi_ibm_validator_executable* + Type: |String| + Default: `'lint-openapi'` + + This variable can be set to change the path to lint-openapi. + + +g:ale_openapi_ibm_validator_options *g:ale_openapi_ibm_validator_options* + *b:ale_openapi_ibm_validator_options* + Type: |String| + Default: `''` + + This variable can be set to pass additional options to lint-openapi. + + +=============================================================================== +prettier *ale-openapi-prettier* + +See |ale-javascript-prettier| for information about the available options. + + +=============================================================================== +yamllint *ale-openapi-yamllint* + +See |ale-yaml-yamllint| for information about the available options. + + +=============================================================================== + vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale-python.txt b/doc/ale-python.txt index f0c8bfb8..1f263e84 100644 --- a/doc/ale-python.txt +++ b/doc/ale-python.txt @@ -36,6 +36,8 @@ ALE will look for configuration files with the following filenames. > .pylintrc Pipfile Pipfile.lock + poetry.lock + pyproject.toml < The first directory containing any of the files named above will be used. @@ -280,6 +282,15 @@ g:ale_python_isort_use_global *g:ale_python_isort_use_global* See |ale-integrations-local-executables| +g:ale_python_isort_auto_pipenv *g:ale_python_isort_auto_pipenv* + *b:ale_python_isort_auto_pipenv* + Type: |Number| + Default: `0` + + Detect whether the file is inside a pipenv, and set the executable to `pipenv` + if true. This is overridden by a manually-set executable. + + =============================================================================== mypy *ale-python-mypy* diff --git a/doc/ale-ruby.txt b/doc/ale-ruby.txt index 8815404a..edc6144a 100644 --- a/doc/ale-ruby.txt +++ b/doc/ale-ruby.txt @@ -177,6 +177,16 @@ g:ale_ruby_sorbet_options *g:ale_ruby_sorbet_options* This variable can be changed to modify flags given to sorbet. +g:ale_ruby_sorbet_enable_watchman *g:ale_ruby_sorbet_enable_watchman* + *b:ale_ruby_sorbet_enable_watchman* + Type: |Number| + Default: `0` + + Whether or not to use watchman to let the LSP server to know about changes + to files from outside of vim. Defaults to disable watchman because it + requires watchman to be installed separately from sorbet. + + =============================================================================== standardrb *ale-ruby-standardrb* diff --git a/doc/ale-salt.tmt b/doc/ale-salt.tmt new file mode 100644 index 00000000..ac500d37 --- /dev/null +++ b/doc/ale-salt.tmt @@ -0,0 +1,43 @@ +=============================================================================== +ALE SALT Integration *ale-salt-options* + +=============================================================================== +salt-lint *ale-salt-salt-lint* + +Website: https://github.com/warpnet/salt-lint + + +Installation +------------------------------------------------------------------------------- + +Install salt-lint in your a virtualenv directory, locally, or globally: > + + pip install salt-lint # After activating virtualenv + pip install --user salt-lint # Install to ~/.local/bin + sudo pip install salt-lint # Install globally + +See |g:ale_virtualenv_dir_names| for configuring how ALE searches for +virtualenv directories. + + +Options +------------------------------------------------------------------------------- + +g:ale_salt_salt-lint_executable *g:ale_salt_salt_lint_executable* + *b:ale_salt_salt_lint_executable* + Type: |String| + Default: `'salt-lint'` + + This variable can be set to change the path to salt-lint. + + +g:ale_salt_salt-lint_options *g:ale_salt_salt-lint_options* + *b:ale_salt_salt-lint_options* + Type: |String| + Default: `''` + + This variable can be set to pass additional options to salt-lint. + + +=============================================================================== + vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale-supported-languages-and-tools.txt b/doc/ale-supported-languages-and-tools.txt index 36e27932..72c685c5 100644 --- a/doc/ale-supported-languages-and-tools.txt +++ b/doc/ale-supported-languages-and-tools.txt @@ -13,12 +13,16 @@ Notes: `!!` These linters check only files on disk. See |ale-lint-file-linters| * Ada + * `ada_language_server` * `gcc` * `gnatpp` * Ansible * `ansible-lint` * API Blueprint * `drafter` +* APKBUILD + * `apkbuild-lint` + * `secfixes-check` * AsciiDoc * `alex`!! * `languagetool`!! @@ -49,8 +53,8 @@ Notes: * `astyle` * `ccls` * `clang` (`cc`) - * `clangd` * `clang-format` + * `clangd` * `clangtidy`!! * `cppcheck` * `cpplint`!! @@ -67,9 +71,9 @@ Notes: * `astyle` * `ccls` * `clang` (`cc`) + * `clang-format` * `clangcheck`!! * `clangd` - * `clang-format` * `clangtidy`!! * `clazy`!! * `cppcheck` @@ -116,11 +120,14 @@ Notes: * Dafny * `dafny`!! * Dart + * `analysis_server` * `dartanalyzer`!! * `dartfmt`!! * `language_server` * Dhall * `dhall-format` + * `dhall-freeze` + * `dhall-lint` * Dockerfile * `dockerfile_lint` * `hadolint` @@ -140,9 +147,9 @@ Notes: * `erubis` * `ruumba` * Erlang + * `SyntaxErl` * `elvis`!! * `erlc` - * `SyntaxErl` * Fish * `fish` (-n flag) * Fortran @@ -160,17 +167,17 @@ Notes: * Go * `bingo` * `go build`!! + * `go mod`!! + * `go vet`!! * `gofmt` * `goimports` * `golangci-lint`!! * `golangserver` * `golint` * `gometalinter`!! - * `go mod`!! * `gopls` * `gosimple`!! * `gotype`!! - * `go vet`!! * `revive`!! * `staticcheck`!! * GraphQL @@ -196,6 +203,7 @@ Notes: * `hie` * `hindent` * `hlint` + * `hls` * `ormolu` * `stack-build`!! * `stack-ghc` @@ -203,10 +211,10 @@ Notes: * HCL * `terraform-fmt` * HTML + * `HTMLHint` * `alex`!! * `fecs` * `html-beautify` - * `HTMLHint` * `prettier` * `proselint` * `tidy` @@ -215,15 +223,17 @@ Notes: * `idris` * Ink * `ink-language-server` +* Inko + * `inko` !! * ISPC * `ispc`!! * Java + * `PMD` * `checkstyle` * `eclipselsp` * `google-java-format` * `javac` * `javalsp` - * `PMD` * `uncrustify` * JavaScript * `eslint` @@ -242,6 +252,7 @@ Notes: * `jq` * `jsonlint` * `prettier` + * `spectral` * Julia * `languageserver` * Kotlin @@ -300,6 +311,7 @@ Notes: * nix * `nix-instantiate` * `nixpkgs-fmt` + * `rnix-lsp` * nroff * `alex`!! * `proselint` @@ -318,6 +330,10 @@ Notes: * `ocamlformat` * `ocp-indent` * `ols` +* OpenApi + * `ibm_validator` + * `prettier` + * `yamllint` * Pawn * `uncrustify` * Perl @@ -330,10 +346,10 @@ Notes: * `intelephense` * `langserver` * `phan` + * `php -l` + * `php-cs-fixer` * `phpcbf` * `phpcs` - * `php-cs-fixer` - * `php -l` * `phpmd` * `phpstan` * `psalm`!! @@ -394,6 +410,8 @@ Notes: * `styler` * Racket * `raco` +* Re:VIEW + * `redpen` * ReasonML * `merlin` * `ols` @@ -407,8 +425,6 @@ Notes: * `textlint` * `vale` * `write-good` -* Re:VIEW - * `redpen` * RPM spec * `rpmlint` * Ruby @@ -428,6 +444,8 @@ Notes: * `rust-analyzer` * `rustc` (see |ale-integration-rust|) * `rustfmt` +* Salt + * `salt-lint` * Sass * `sass-lint` * `stylelint` @@ -453,10 +471,10 @@ Notes: * `solium` * SQL * `pgformatter` + * `sql-lint` * `sqlfmt` * `sqlformat` * `sqlint` - * `sql-lint` * Stylus * `stylelint` * SugarSS @@ -469,7 +487,10 @@ Notes: * Tcl * `nagelfar`!! * Terraform - * `fmt` + * `terraform` + * `terraform-fmt-fixer` + * `terraform-ls` + * `terraform-lsp` * `tflint` * Texinfo * `alex`!! @@ -486,6 +507,7 @@ Notes: * Thrift * `thrift` * TypeScript + * `deno` * `eslint` * `fecs` * `prettier` @@ -495,6 +517,7 @@ Notes: * `typecheck` * VALA * `uncrustify` + * `vala_lint`!! * Verilog * `hdl-checker` * `iverilog` @@ -523,6 +546,7 @@ Notes: * `xmllint` * YAML * `prettier` + * `spectral` * `swaglint` * `yamlfix` * `yamllint` diff --git a/doc/ale-terraform.txt b/doc/ale-terraform.txt index f62db190..175bdf5c 100644 --- a/doc/ale-terraform.txt +++ b/doc/ale-terraform.txt @@ -33,6 +33,28 @@ g:ale_terraform_terraform_executable *g:ale_terraform_terraform_executable* =============================================================================== +terraform-ls *ale-terraform-terraform-ls* + +Official terraform language server. More stable than *terraform-lsp* but +currently has less features. + +g:ale_terraform_ls_executable *g:ale_terraform_ls_executable* + *b:ale_terraform_ls_executable* + Type: |String| + Default: `'terraform-ls'` + + This variable can be changed to use a different executable for terraform-ls. + + +g:ale_terraform_ls_options *g:ale_terraform_ls_options* + *b:ale_terraform_ls_options* + Type: |String| + Default: `''` + + This variable can be changed to pass custom CLI flags to terraform-ls. + + +=============================================================================== terraform-lsp *ale-terraform-terraform-lsp* g:ale_terraform_langserver_executable *g:ale_terraform_langserver_executable* diff --git a/doc/ale-typescript.txt b/doc/ale-typescript.txt index 2c50d119..a2446c2c 100644 --- a/doc/ale-typescript.txt +++ b/doc/ale-typescript.txt @@ -3,6 +3,39 @@ ALE TypeScript Integration *ale-typescript-options* =============================================================================== +deno *ale-typescript-deno* + +Starting from version 1.6.0, Deno comes with its own language server. Earlier +versions are not supported. + +g:ale_deno_executable *g:ale_deno_executable* + *b:ale_deno_executable* + Type: |String| + Default: `'deno'` + + +g:ale_deno_lsp_project_root *g:ale_deno_lsp_project_root* + *b:ale_deno_lsp_project_root* + Type: |String| + Default: `''` + + If this variable is left unset, ALE will try to find the project root by + executing the following steps in the given order: + + 1. Find an ancestor directory containing a tsconfig.json. + 2. Find an ancestory irectory containing a .git folder. + 3. Use the directory of the current buffer (if the buffer was opened from + a file). + +g:ale_deno_unstable *g:ale_deno_unstable* + *b:ale_deno_unstable* + Type: |Number| + Default: `0` + + Enable or disable unstable Deno features and APIs. + + +=============================================================================== eslint *ale-typescript-eslint* Because of how TypeScript compiles code to JavaScript and how interrelated @@ -139,4 +172,31 @@ g:ale_typescript_tsserver_use_global *g:ale_typescript_tsserver_use_global* =============================================================================== +xo *ale-typescript-xo* + +g:ale_typescript_xo_executable *g:ale_typescript_xo_executable* + *b:ale_typescript_xo_executable* + Type: |String| + Default: `'xo'` + + See |ale-integrations-local-executables| + + +g:ale_typescript_xo_options *g:ale_typescript_xo_options* + *b:ale_typescript_xo_options* + Type: |String| + Default: `''` + + This variable can be set to pass additional options to xo. + + +g:ale_typescript_xo_use_global *g:ale_typescript_xo_use_global* + *b:ale_typescript_xo_use_global* + Type: |Number| + Default: `get(g:, 'ale_use_global_executables', 0)` + + See |ale-integrations-local-executables| + + +=============================================================================== vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale-vala.txt b/doc/ale-vala.txt index ca24bcf4..d48f68bb 100644 --- a/doc/ale-vala.txt +++ b/doc/ale-vala.txt @@ -9,4 +9,25 @@ See |ale-c-uncrustify| for information about the available options. =============================================================================== +Vala-Lint *ale-vala-vala-lint* + +g:vala_vala_lint_executable *g:vala_vala_lint_executable* + *b:vala_vala_lint_executable* + Type: |String| + Default: `'io.elementary.vala-lint'` + + This variable can be set to specify a Vala-Lint executable file. + + +g:vala_vala_lint_config_filename *g:vala_vala_lint_config_filename* + *b:vala_vala_lint_config_filename* + Type: |String| + Default: `'vala-lint.conf'` + + This variable can be set to specify a Vala-Lint config filename. When a file + with the specified name was not found or this variable was set to empty, + Vala-Lint will be executed without specifying a config filename. + + +=============================================================================== vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl: diff --git a/doc/ale-yaml.txt b/doc/ale-yaml.txt index 61bfc139..04871403 100644 --- a/doc/ale-yaml.txt +++ b/doc/ale-yaml.txt @@ -16,6 +16,38 @@ Install prettier either globally or locally: > npm install prettier # local < =============================================================================== +spectral *ale-yaml-spectral* + +Website: https://github.com/stoplightio/spectral + +Installation +------------------------------------------------------------------------------- + +Install spectral either globally or locally: > + + npm install @stoplight/spectral -g # global + npm install @stoplight/spectral # local +< + +Options +------------------------------------------------------------------------------- + +g:ale_yaml_spectral_executable *g:ale_yaml_spectral_executable* + *b:ale_yaml_spectral_executable* + Type: |String| + Default: `'spectral'` + + This variable can be set to change the path to spectral. + +g:ale_yaml_spectral_use_global *g:ale_yaml_spectral_use_global* + *b:ale_yaml_spectral_use_global* + Type: |String| + Default: `get(g:, 'ale_use_global_executables', 0)` + + See |ale-integrations-local-executables| + + +=============================================================================== swaglint *ale-yaml-swaglint* Website: https://github.com/byCedric/swaglint diff --git a/doc/ale.txt b/doc/ale.txt index f9f40d12..9268c9f2 100644 --- a/doc/ale.txt +++ b/doc/ale.txt @@ -228,8 +228,8 @@ A minimal configuration for a language server linter might look so. > \ 'project_root': '/path/to/root_of_project', \}) < -For language servers that use a TCP socket connection, you should define the -address to connect to instead. > +For language servers that use a TCP or named pipe socket connection, you +should define the address to connect to instead. > call ale#linter#Define('filetype_here', { \ 'name': 'any_name_you_want', @@ -646,6 +646,9 @@ problem will be displayed in a balloon instead of hover information. Hover information can be displayed in the preview window instead by setting |g:ale_hover_to_preview| to `1`. +When using Neovim, if |g:ale_hover_to_floating_preview| or |g:ale_floating_preview| +is set to 1, the hover information will show in a floating window. + For Vim 8.1+ terminals, mouse hovering is disabled by default. Enabling |balloonexpr| commands in terminals can cause scrolling issues in terminals, so ALE will not attempt to show balloons unless |g:ale_set_balloons| is set to @@ -954,6 +957,15 @@ g:ale_default_navigation *g:ale_default_navigation* buffer, such as for |ALEFindReferences|, or |ALEGoToDefinition|. +g:ale_detail_to_floating_preview *g:ale_detail_to_floating_preview* + *b:ale_detail_to_floating_preview* + Type: |Number| + Default: `0` + + When this option is set to `1`, Neovim will use a floating window for + ALEDetail output. + + g:ale_disable_lsp *g:ale_disable_lsp* *b:ale_disable_lsp* @@ -1177,6 +1189,16 @@ g:ale_fix_on_save_ignore *g:ale_fix_on_save_ignore* let g:ale_fix_on_save_ignore = [g:AddBar] < +g:ale_floating_preview *g:ale_floating_preview* + + Type: |Number| + Default: `0` + + When set to `1`, Neovim will use a floating window for ale's preview window. + This is equivalent to setting |g:ale_hover_to_floating_preview| and + |g:ale_detail_to_floating_preview| to `1`. + + g:ale_history_enabled *g:ale_history_enabled* Type: |Number| @@ -1235,6 +1257,14 @@ g:ale_hover_to_preview *g:ale_hover_to_preview* instead of in balloons or the message line. +g:ale_hover_to_floating_preview *g:ale_hover_to_floating_preview* + *b:ale_hover_to_floating_preview* + Type: |Number| + Default: `0` + + If set to `1`, Neovim will use floating windows for hover messages. + + g:ale_keep_list_window_open *g:ale_keep_list_window_open* *b:ale_keep_list_window_open* Type: |Number| @@ -1526,11 +1556,13 @@ g:ale_linters *g:ale_linters* following values: > { + \ 'apkbuild': ['apkbuild_lint', 'secfixes_check'], \ 'csh': ['shell'], \ 'elixir': ['credo', 'dialyxir', 'dogma'], \ 'go': ['gofmt', 'golint', 'go vet'], \ 'hack': ['hack'], \ 'help': [], + \ 'inko': ['inko'], \ 'perl': ['perlcritic'], \ 'perl6': [], \ 'python': ['flake8', 'mypy', 'pylint', 'pyright'], @@ -1677,6 +1709,15 @@ g:ale_lsp_show_message_severity *g:ale_lsp_show_message_severity* `'disabled'` - Doesn't display any information at all. +g:ale_lsp_suggestions *g:ale_lsp_suggestions* + + Type: |Number| + Default: 1 + + This variable defines if suggestions must be collected from LSP or tsserver + and shown. + + g:ale_lsp_root *g:ale_lsp_root* *b:ale_lsp_root* @@ -1812,6 +1853,8 @@ g:ale_popup_menu_enabled *g:ale_popup_menu_enabled* capabilities in the right click mouse menu when there's a LSP server or tsserver available. See |ale-refactor|. + This feature is only supported in GUI versions of Vim. + This setting must be set to `1` before ALE is loaded for this behavior to be enabled. See |ale-lint-settings-on-startup|. @@ -2556,8 +2599,12 @@ documented in additional help files. ada.....................................|ale-ada-options| gcc...................................|ale-ada-gcc| gnatpp................................|ale-ada-gnatpp| + ada-language-server...................|ale-ada-language-server| ansible.................................|ale-ansible-options| ansible-lint..........................|ale-ansible-ansible-lint| + apkbuild................................|ale-apkbuild-options| + apkbuild-lint.........................|ale-apkbuild-apkbuild-lint| + secfixes-check........................|ale-apkbuild-secfixes-check| asciidoc................................|ale-asciidoc-options| write-good............................|ale-asciidoc-write-good| textlint..............................|ale-asciidoc-textlint| @@ -2621,9 +2668,16 @@ documented in additional help files. dfmt..................................|ale-d-dfmt| dls...................................|ale-d-dls| uncrustify............................|ale-d-uncrustify| + dafny...................................|ale-dafny-options| + dafny.................................|ale-dafny-dafny| dart....................................|ale-dart-options| + analysis_server.......................|ale-dart-analysis_server| dartanalyzer..........................|ale-dart-dartanalyzer| dartfmt...............................|ale-dart-dartfmt| + dhall...................................|ale-dhall-options| + dhall-format..........................|ale-dhall-format| + dhall-freeze..........................|ale-dhall-freeze| + dhall-lint............................|ale-dhall-lint| dockerfile..............................|ale-dockerfile-options| dockerfile_lint.......................|ale-dockerfile-dockerfile_lint| hadolint..............................|ale-dockerfile-hadolint| @@ -2689,6 +2743,7 @@ documented in additional help files. hfmt..................................|ale-haskell-hfmt| hindent...............................|ale-haskell-hindent| hlint.................................|ale-haskell-hlint| + hls...................................|ale-haskell-hls| stack-build...........................|ale-haskell-stack-build| stack-ghc.............................|ale-haskell-stack-ghc| stylish-haskell.......................|ale-haskell-stylish-haskell| @@ -2708,6 +2763,8 @@ documented in additional help files. idris.................................|ale-idris-idris| ink.....................................|ale-ink-options| ink-language-server...................|ale-ink-language-server| + inko....................................|ale-inko-options| + inko..................................|ale-inko-inko| ispc....................................|ale-ispc-options| ispc..................................|ale-ispc-ispc| java....................................|ale-java-options| @@ -2735,6 +2792,7 @@ documented in additional help files. jsonlint..............................|ale-json-jsonlint| jq....................................|ale-json-jq| prettier..............................|ale-json-prettier| + spectral..............................|ale-json-spectral| julia...................................|ale-julia-options| languageserver........................|ale-julia-languageserver| kotlin..................................|ale-kotlin-options| @@ -2787,6 +2845,10 @@ documented in additional help files. ols...................................|ale-ocaml-ols| ocamlformat...........................|ale-ocaml-ocamlformat| ocp-indent............................|ale-ocaml-ocp-indent| + openapi.................................|ale-openapi-options| + ibm_validator.........................|ale-openapi-ibm-validator| + prettier..............................|ale-openapi-prettier| + yamllint..............................|ale-openapi-yamllint| pawn....................................|ale-pawn-options| uncrustify............................|ale-pawn-uncrustify| perl....................................|ale-perl-options| @@ -2882,6 +2944,8 @@ documented in additional help files. rls...................................|ale-rust-rls| rustc.................................|ale-rust-rustc| rustfmt...............................|ale-rust-rustfmt| + salt....................................|ale-salt-options| + salt-lint.............................|ale-salt-salt-lint| sass....................................|ale-sass-options| sasslint..............................|ale-sass-sasslint| stylelint.............................|ale-sass-stylelint| @@ -2923,6 +2987,7 @@ documented in additional help files. terraform...............................|ale-terraform-options| terraform-fmt-fixer...................|ale-terraform-fmt-fixer| terraform.............................|ale-terraform-terraform| + terraform-ls..........................|ale-terraform-terraform-ls| terraform-lsp.........................|ale-terraform-terraform-lsp| tflint................................|ale-terraform-tflint| tex.....................................|ale-tex-options| @@ -2938,11 +3003,13 @@ documented in additional help files. thrift..................................|ale-thrift-options| thrift................................|ale-thrift-thrift| typescript..............................|ale-typescript-options| + deno..................................|ale-typescript-deno| eslint................................|ale-typescript-eslint| prettier..............................|ale-typescript-prettier| standard..............................|ale-typescript-standard| tslint................................|ale-typescript-tslint| tsserver..............................|ale-typescript-tsserver| + xo....................................|ale-typescript-xo| vala....................................|ale-vala-options| uncrustify............................|ale-vala-uncrustify| verilog/systemverilog...................|ale-verilog-options| @@ -2956,11 +3023,11 @@ documented in additional help files. hdl-checker...........................|ale-vhdl-hdl-checker| vcom..................................|ale-vhdl-vcom| xvhdl.................................|ale-vhdl-xvhdl| + vim help................................|ale-vim-help-options| + write-good............................|ale-vim-help-write-good| vim.....................................|ale-vim-options| vimls.................................|ale-vim-vimls| vint..................................|ale-vim-vint| - vim help................................|ale-vim-help-options| - write-good............................|ale-vim-help-write-good| vue.....................................|ale-vue-options| prettier..............................|ale-vue-prettier| vls...................................|ale-vue-vls| @@ -2970,6 +3037,7 @@ documented in additional help files. xmllint...............................|ale-xml-xmllint| yaml....................................|ale-yaml-options| prettier..............................|ale-yaml-prettier| + spectral..............................|ale-yaml-spectral| swaglint..............................|ale-yaml-swaglint| yamlfix...............................|ale-yaml-yamlfix| yamllint..............................|ale-yaml-yamllint| @@ -3788,7 +3856,7 @@ ale#linter#Define(filetype, linter) *ale#linter#Define()* When this argument is set to `'socket'`, then the linter will be defined as an LSP linter via a TCP - socket connection. `address` must be set. + or named pipe socket connection. `address` must be set. ALE will not start a server automatically. @@ -3813,7 +3881,10 @@ ale#linter#Define(filetype, linter) *ale#linter#Define()* `address` A |String| representing an address to connect to, or a |Funcref| accepting a buffer number and - returning the |String|. + returning the |String|. If the value contains a + colon, it is interpreted as referring to a TCP + socket; otherwise it is interpreted as the path of a + named pipe. The result can be computed with |ale#command#Run()|. diff --git a/plugin/ale.vim b/plugin/ale.vim index 5b7be116..1735715d 100644 --- a/plugin/ale.vim +++ b/plugin/ale.vim @@ -138,6 +138,15 @@ let g:ale_set_balloons = get(g:, 'ale_set_balloons', has('balloon_eval') && has( " Use preview window for hover messages. let g:ale_hover_to_preview = get(g:, 'ale_hover_to_preview', 0) +" Float preview windows in Neovim +let g:ale_floating_preview = get(g:, 'ale_floating_preview', 0) + +" Hovers use floating windows in Neovim +let g:ale_hover_to_floating_preview = get(g:, 'ale_hover_to_floating_preview', 0) + +" Detail uses floating windows in Neovim +let g:ale_detail_to_floating_preview = get(g:, 'ale_detail_to_floating_preview', 0) + " This flag can be set to 0 to disable warnings for trailing whitespace let g:ale_warn_about_trailing_whitespace = get(g:, 'ale_warn_about_trailing_whitespace', 1) " This flag can be set to 0 to disable warnings for trailing blank lines @@ -9,8 +9,11 @@ set -u # options, or read the output below. # -image=w0rp/ale -current_image_id=f58c7bf8900f +image=denseanalysis/ale + +# Create docker image tag based on Dockerfile contents +image_tag=$(md5sum Dockerfile | cut -d' ' -f1) +git_version=$(git describe --always --tags) # Used in all test scripts for running the selected Docker image. DOCKER_RUN_IMAGE="$image" @@ -21,9 +24,9 @@ tests='test/*.vader test/*/*.vader test/*/*/*.vader test/*/*/*.vader' verbose_flag='' quiet_flag='' run_neovim_02_tests=1 -run_neovim_03_tests=1 +run_neovim_04_tests=1 run_vim_80_tests=1 -run_vim_81_tests=1 +run_vim_82_tests=1 run_linters=1 while [ $# -ne 0 ]; do @@ -36,58 +39,66 @@ while [ $# -ne 0 ]; do quiet_flag='-q' shift ;; + --build-image) + run_vim_80_tests=0 + run_vim_82_tests=0 + run_neovim_02_tests=0 + run_neovim_04_tests=0 + run_linters=0 + shift + ;; --neovim-only) run_vim_80_tests=0 - run_vim_81_tests=0 + run_vim_82_tests=0 run_linters=0 shift ;; --neovim-02-only) - run_neovim_03_tests=0 + run_neovim_04_tests=0 run_vim_80_tests=0 - run_vim_81_tests=0 + run_vim_82_tests=0 run_linters=0 shift ;; - --neovim-03-only) + --neovim-04-only) run_neovim_02_tests=0 run_vim_80_tests=0 - run_vim_81_tests=0 + run_vim_82_tests=0 run_linters=0 shift ;; --vim-only) run_neovim_02_tests=0 - run_neovim_03_tests=0 + run_neovim_04_tests=0 run_linters=0 shift ;; --vim-80-only) run_neovim_02_tests=0 - run_neovim_03_tests=0 - run_vim_81_tests=0 + run_neovim_04_tests=0 + run_vim_82_tests=0 run_linters=0 shift ;; - --vim-81-only) + --vim-82-only) run_neovim_02_tests=0 - run_neovim_03_tests=0 + run_neovim_04_tests=0 run_vim_80_tests=0 run_linters=0 shift ;; --linters-only) run_vim_80_tests=0 - run_vim_81_tests=0 + run_vim_82_tests=0 run_neovim_02_tests=0 - run_neovim_03_tests=0 + run_neovim_04_tests=0 shift ;; --fast) run_vim_80_tests=0 - run_vim_81_tests=0 + run_vim_82_tests=0 run_neovim_02_tests=0 - run_neovim_03_tests=1 + run_neovim_04_tests=1 shift ;; --help) @@ -99,12 +110,13 @@ while [ $# -ne 0 ]; do echo 'Options:' echo ' -v Enable verbose output' echo ' -q Hide output for successful tests' - echo ' --neovim-only Run tests only for NeoVim 0.2 and 0.3' + echo ' --build-image Run docker image build only.' + echo ' --neovim-only Run tests only for NeoVim' echo ' --neovim-02-only Run tests only for NeoVim 0.2' - echo ' --neovim-03-only Run tests only for NeoVim 0.3' - echo ' --vim-only Run tests only for Vim 8.0 and 8.1' + echo ' --neovim-04-only Run tests only for NeoVim 0.4' + echo ' --vim-only Run tests only for Vim' echo ' --vim-80-only Run tests only for Vim 8.0' - echo ' --vim-81-only Run tests only for Vim 8.1' + echo ' --vim-82-only Run tests only for Vim 8.2' echo ' --linters-only Run only Vint and custom checks' echo ' --fast Run only the fastest Vim and custom checks' echo ' --help Show this help text' @@ -138,8 +150,36 @@ fi # Delete .swp files in the test directory, which cause Vim 8 to hang. find test -name '*.swp' -delete -docker images -q w0rp/ale | grep "^$current_image_id" > /dev/null \ - || docker pull "$image" +# Check if docker un image is available locally +has_image=$(docker images ls --filter reference="${image}:${image_tag}" --quiet | wc -l) + +if [ "$has_image" -eq 0 ] +then + + echo "Downloading run image ${image}:${image_tag}" + docker pull "${image}:${image_tag}" &> /dev/null + + if [ $? -eq 1 ] + then + echo "Could not pull image ${image}:${image_tag}" + echo "Building run image ${image}:${image_tag}" + docker build --build-arg GIT_VERSION="$git_version" -t "${image}:${image_tag}" . + docker tag "${image}:${image_tag}" "${image}:latest" + + if [[ -z "${DOCKER_HUB_USER:-}" || -z "${DOCKER_HUB_PASS:-}" ]] + then + echo "Docker Hub credentials not set, skip push" + else + echo "Push ${image}:${image_tag} to Docker Hub" + echo "$DOCKER_HUB_PASS" | docker login -u "$DOCKER_HUB_USER" --password-stdin + docker push "${image}:${image_tag}" + fi + fi +else + echo "Docker run image ${image}:${image_tag} ready" +fi + +docker tag "${image}:${image_tag}" "${image}:latest" output_dir=$(mktemp -d 2>/dev/null || mktemp -d -t 'mytmpdir') @@ -174,9 +214,9 @@ trap cancel_tests INT TERM for vim in $(docker run --rm "$DOCKER_RUN_IMAGE" ls /vim-build/bin | grep '^neovim\|^vim' ); do if ( [[ $vim =~ ^vim-v8.0 ]] && ((run_vim_80_tests)) ) \ - || ( [[ $vim =~ ^vim-v8.1 ]] && ((run_vim_81_tests)) ) \ + || ( [[ $vim =~ ^vim-v8.2 ]] && ((run_vim_82_tests)) ) \ || ( [[ $vim =~ ^neovim-v0.2 ]] && ((run_neovim_02_tests)) ) \ - || ( [[ $vim =~ ^neovim-v0.3 ]] && ((run_neovim_03_tests)) ); then + || ( [[ $vim =~ ^neovim-v0.4 ]] && ((run_neovim_04_tests)) ); then echo "Starting Vim: $vim..." file_number=$((file_number+1)) test/script/run-vader-tests $quiet_flag $verbose_flag "$vim" "$tests" \ diff --git a/supported-tools.md b/supported-tools.md index 96ef273b..e449ff39 100644 --- a/supported-tools.md +++ b/supported-tools.md @@ -22,12 +22,16 @@ formatting. --- * Ada + * [ada_language_server](https://github.com/AdaCore/ada_language_server) * [gcc](https://gcc.gnu.org) * [gnatpp](https://docs.adacore.com/gnat_ugn-docs/html/gnat_ugn/gnat_ugn/gnat_utility_programs.html#the-gnat-pretty-printer-gnatpp) :floppy_disk: * Ansible * [ansible-lint](https://github.com/willthames/ansible-lint) * API Blueprint * [drafter](https://github.com/apiaryio/drafter) +* APKBUILD + * [apkbuild-lint](https://gitlab.alpinelinux.org/Leo/atools) + * [secfixes-check](https://gitlab.alpinelinux.org/Leo/atools) * AsciiDoc * [alex](https://github.com/wooorm/alex) :floppy_disk: * [languagetool](https://languagetool.org/) :floppy_disk: @@ -58,8 +62,8 @@ formatting. * [astyle](http://astyle.sourceforge.net/) * [ccls](https://github.com/MaskRay/ccls) * [clang](http://clang.llvm.org/) - * [clangd](https://clang.llvm.org/extra/clangd.html) * [clang-format](https://clang.llvm.org/docs/ClangFormat.html) + * [clangd](https://clang.llvm.org/extra/clangd.html) * [clangtidy](http://clang.llvm.org/extra/clang-tidy/) :floppy_disk: * [cppcheck](http://cppcheck.sourceforge.net) * [cpplint](https://github.com/google/styleguide/tree/gh-pages/cpplint) @@ -76,9 +80,9 @@ formatting. * [astyle](http://astyle.sourceforge.net/) * [ccls](https://github.com/MaskRay/ccls) * [clang](http://clang.llvm.org/) + * [clang-format](https://clang.llvm.org/docs/ClangFormat.html) * [clangcheck](http://clang.llvm.org/docs/ClangCheck.html) :floppy_disk: * [clangd](https://clang.llvm.org/extra/clangd.html) - * [clang-format](https://clang.llvm.org/docs/ClangFormat.html) * [clangtidy](http://clang.llvm.org/extra/clang-tidy/) :floppy_disk: * [clazy](https://github.com/KDE/clazy) :floppy_disk: * [cppcheck](http://cppcheck.sourceforge.net) @@ -125,11 +129,14 @@ formatting. * Dafny * [dafny](https://rise4fun.com/Dafny) :floppy_disk: * Dart + * [analysis_server](https://github.com/dart-lang/sdk/tree/master/pkg/analysis_server) * [dartanalyzer](https://github.com/dart-lang/sdk/tree/master/pkg/analyzer_cli) :floppy_disk: * [dartfmt](https://github.com/dart-lang/sdk/tree/master/utils/dartfmt) * [language_server](https://github.com/natebosch/dart_language_server) * Dhall * [dhall-format](https://github.com/dhall-lang/dhall-lang) + * [dhall-freeze](https://github.com/dhall-lang/dhall-lang) + * [dhall-lint](https://github.com/dhall-lang/dhall-lang) * Dockerfile * [dockerfile_lint](https://github.com/projectatomic/dockerfile_lint) * [hadolint](https://github.com/hadolint/hadolint) @@ -149,9 +156,9 @@ formatting. * [erubis](https://github.com/kwatch/erubis) * [ruumba](https://github.com/ericqweinstein/ruumba) * Erlang + * [SyntaxErl](https://github.com/ten0s/syntaxerl) * [elvis](https://github.com/inaka/elvis) :floppy_disk: * [erlc](http://erlang.org/doc/man/erlc.html) - * [SyntaxErl](https://github.com/ten0s/syntaxerl) * Fish * fish [-n flag](https://linux.die.net/man/1/fish) * Fortran @@ -169,17 +176,17 @@ formatting. * Go * [bingo](https://github.com/saibing/bingo) :warning: * [go build](https://golang.org/cmd/go/) :warning: :floppy_disk: + * [go mod](https://golang.org/cmd/go/) :warning: :floppy_disk: + * [go vet](https://golang.org/cmd/vet/) :floppy_disk: * [gofmt](https://golang.org/cmd/gofmt/) * [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports) :warning: * [golangci-lint](https://github.com/golangci/golangci-lint) :warning: :floppy_disk: * [golangserver](https://github.com/sourcegraph/go-langserver) :warning: * [golint](https://godoc.org/github.com/golang/lint) * [gometalinter](https://github.com/alecthomas/gometalinter) :warning: :floppy_disk: - * [go mod](https://golang.org/cmd/go/) :warning: :floppy_disk: * [gopls](https://github.com/golang/go/wiki/gopls) :warning: * [gosimple](https://github.com/dominikh/go-tools/tree/master/cmd/gosimple) :warning: :floppy_disk: * [gotype](https://godoc.org/golang.org/x/tools/cmd/gotype) :warning: :floppy_disk: - * [go vet](https://golang.org/cmd/vet/) :floppy_disk: * [revive](https://github.com/mgechev/revive) :warning: :floppy_disk: * [staticcheck](https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck) :warning: :floppy_disk: * GraphQL @@ -205,6 +212,7 @@ formatting. * [hie](https://github.com/haskell/haskell-ide-engine) * [hindent](https://hackage.haskell.org/package/hindent) * [hlint](https://hackage.haskell.org/package/hlint) + * [hls](https://github.com/haskell/haskell-language-server) * [ormolu](https://github.com/tweag/ormolu) * [stack-build](https://haskellstack.org/) :floppy_disk: * [stack-ghc](https://haskellstack.org/) @@ -212,10 +220,10 @@ formatting. * HCL * [terraform-fmt](https://github.com/hashicorp/terraform) * HTML + * [HTMLHint](http://htmlhint.com/) * [alex](https://github.com/wooorm/alex) :floppy_disk: * [fecs](http://fecs.baidu.com/) * [html-beautify](https://beautifier.io/) - * [HTMLHint](http://htmlhint.com/) * [prettier](https://github.com/prettier/prettier) * [proselint](http://proselint.com/) * [tidy](http://www.html-tidy.org/) @@ -224,15 +232,17 @@ formatting. * [idris](http://www.idris-lang.org/) * Ink * [ink-language-server](https://github.com/ephread/ink-language-server) +* Inko + * [inko](https://inko-lang.org/) :floppy_disk: * ISPC * [ispc](https://ispc.github.io/) :floppy_disk: * Java + * [PMD](https://pmd.github.io/) * [checkstyle](http://checkstyle.sourceforge.net) * [eclipselsp](https://github.com/eclipse/eclipse.jdt.ls) * [google-java-format](https://github.com/google/google-java-format) * [javac](http://www.oracle.com/technetwork/java/javase/downloads/index.html) * [javalsp](https://github.com/georgewfraser/vscode-javac) - * [PMD](https://pmd.github.io/) * [uncrustify](https://github.com/uncrustify/uncrustify) * JavaScript * [eslint](http://eslint.org/) @@ -251,6 +261,7 @@ formatting. * [jq](https://stedolan.github.io/jq/) * [jsonlint](http://zaa.ch/jsonlint/) * [prettier](https://github.com/prettier/prettier) + * [spectral](https://github.com/stoplightio/spectral) * Julia * [languageserver](https://github.com/JuliaEditorSupport/LanguageServer.jl) * Kotlin @@ -309,6 +320,7 @@ formatting. * nix * [nix-instantiate](http://nixos.org/nix/manual/#sec-nix-instantiate) * [nixpkgs-fmt](https://github.com/nix-community/nixpkgs-fmt) + * [rnix-lsp](https://github.com/nix-community/rnix-lsp) * nroff * [alex](https://github.com/wooorm/alex) :floppy_disk: * [proselint](http://proselint.com/) @@ -327,6 +339,10 @@ formatting. * [ocamlformat](https://github.com/ocaml-ppx/ocamlformat) * [ocp-indent](https://github.com/OCamlPro/ocp-indent) * [ols](https://github.com/freebroccolo/ocaml-language-server) +* OpenApi + * [ibm_validator](https://github.com/IBM/openapi-validator) + * [prettier](https://github.com/prettier/prettier) + * [yamllint](https://yamllint.readthedocs.io/) * Pawn * [uncrustify](https://github.com/uncrustify/uncrustify) * Perl @@ -339,10 +355,10 @@ formatting. * [intelephense](https://github.com/bmewburn/intelephense-docs) * [langserver](https://github.com/felixfbecker/php-language-server) * [phan](https://github.com/phan/phan) see `:help ale-php-phan` to instructions + * [php -l](https://secure.php.net/) + * [php-cs-fixer](http://cs.sensiolabs.org/) * [phpcbf](https://github.com/squizlabs/PHP_CodeSniffer) * [phpcs](https://github.com/squizlabs/PHP_CodeSniffer) - * [php-cs-fixer](http://cs.sensiolabs.org/) - * [php -l](https://secure.php.net/) * [phpmd](https://phpmd.org) * [phpstan](https://github.com/phpstan/phpstan) * [psalm](https://getpsalm.org) :floppy_disk: @@ -403,6 +419,8 @@ formatting. * [styler](https://github.com/r-lib/styler) * Racket * [raco](https://docs.racket-lang.org/raco/) +* Re:VIEW + * [redpen](http://redpen.cc/) * ReasonML * [merlin](https://github.com/the-lambda-church/merlin) see `:help ale-reasonml-ols` for configuration instructions * [ols](https://github.com/freebroccolo/ocaml-language-server) @@ -416,8 +434,6 @@ formatting. * [textlint](https://textlint.github.io/) * [vale](https://github.com/ValeLint/vale) * [write-good](https://github.com/btford/write-good) -* Re:VIEW - * [redpen](http://redpen.cc/) * RPM spec * [rpmlint](https://github.com/rpm-software-management/rpmlint) :warning: (see `:help ale-integration-spec`) * Ruby @@ -437,6 +453,8 @@ formatting. * [rust-analyzer](https://github.com/rust-analyzer/rust-analyzer) :warning: * [rustc](https://www.rust-lang.org/) :warning: * [rustfmt](https://github.com/rust-lang-nursery/rustfmt) +* Salt + * [salt-lint](https://github.com/warpnet/salt-lint) * Sass * [sass-lint](https://www.npmjs.com/package/sass-lint) * [stylelint](https://github.com/stylelint/stylelint) @@ -462,10 +480,10 @@ formatting. * [solium](https://github.com/duaraghav8/Solium) * SQL * [pgformatter](https://github.com/darold/pgFormatter) + * [sql-lint](https://github.com/joereynolds/sql-lint) * [sqlfmt](https://github.com/jackc/sqlfmt) * [sqlformat](https://github.com/andialbrecht/sqlparse) * [sqlint](https://github.com/purcell/sqlint) - * [sql-lint](https://github.com/joereynolds/sql-lint) * Stylus * [stylelint](https://github.com/stylelint/stylelint) * SugarSS @@ -478,7 +496,10 @@ formatting. * Tcl * [nagelfar](http://nagelfar.sourceforge.net) :floppy_disk: * Terraform - * [fmt](https://github.com/hashicorp/terraform) + * [terraform](https://github.com/hashicorp/terraform) + * [terraform-fmt-fixer](https://github.com/hashicorp/terraform) + * [terraform-ls](https://github.com/hashicorp/terraform-ls) + * [terraform-lsp](https://github.com/juliosueiras/terraform-lsp) * [tflint](https://github.com/wata727/tflint) * Texinfo * [alex](https://github.com/wooorm/alex) :floppy_disk: @@ -495,6 +516,7 @@ formatting. * Thrift * [thrift](http://thrift.apache.org/) * TypeScript + * [deno](https://deno.land/) * [eslint](http://eslint.org/) * [fecs](http://fecs.baidu.com/) * [prettier](https://github.com/prettier/prettier) @@ -504,6 +526,7 @@ formatting. * typecheck * VALA * [uncrustify](https://github.com/uncrustify/uncrustify) + * [vala_lint](https://github.com/vala-lang/vala-lint) :floppy_disk: * Verilog * [hdl-checker](https://pypi.org/project/hdl-checker) * [iverilog](https://github.com/steveicarus/iverilog) @@ -532,6 +555,7 @@ formatting. * [xmllint](http://xmlsoft.org/xmllint.html) * YAML * [prettier](https://github.com/prettier/prettier) + * [spectral](https://github.com/stoplightio/spectral) * [swaglint](https://github.com/byCedric/swaglint) * [yamlfix](https://lyz-code.github.io/yamlfix) * [yamllint](https://yamllint.readthedocs.io/) diff --git a/test/command_callback/inko_paths/test.inko b/test/command_callback/inko_paths/test.inko new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/inko_paths/test.inko diff --git a/test/command_callback/inko_paths/tests/test/test_foo.inko b/test/command_callback/inko_paths/tests/test/test_foo.inko new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/inko_paths/tests/test/test_foo.inko diff --git a/test/command_callback/spectral_paths/node_modules/.bin/spectral b/test/command_callback/spectral_paths/node_modules/.bin/spectral new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/spectral_paths/node_modules/.bin/spectral diff --git a/test/command_callback/spectral_paths/openapi.yaml b/test/command_callback/spectral_paths/openapi.yaml new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/command_callback/spectral_paths/openapi.yaml diff --git a/test/command_callback/test_adals_command_callbacks.vader b/test/command_callback/test_adals_command_callbacks.vader new file mode 100644 index 00000000..5a04594e --- /dev/null +++ b/test/command_callback/test_adals_command_callbacks.vader @@ -0,0 +1,17 @@ +Before: + call ale#assert#SetUpLinterTest('ada', 'adals') + +After: + call ale#assert#TearDownLinterTest() + +Execute(Sets adals executable): + let g:ale_ada_adals_executable = '/path/to /Ada' + AssertLinter '/path/to /Ada', ale#Escape('/path/to /Ada') + +Execute(Sets adals encoding): + let b:ale_ada_adals_encoding = 'iso-8859-1' + AssertLSPConfig {'ada.defaultCharset': 'iso-8859-1', 'ada.projectFile': 'default.gpr'} + +Execute(Sets adals project): + let g:ale_ada_adals_project = 'myproject.gpr' + AssertLSPConfig {'ada.defaultCharset': 'utf-8', 'ada.projectFile': 'myproject.gpr'} diff --git a/test/command_callback/test_clang_tidy_command_callback.vader b/test/command_callback/test_clang_tidy_command_callback.vader index f0a07e8c..eb1220be 100644 --- a/test/command_callback/test_clang_tidy_command_callback.vader +++ b/test/command_callback/test_clang_tidy_command_callback.vader @@ -68,7 +68,6 @@ Execute(The build directory should be used for header files): \ ale#Escape('clang-tidy') \ . ' -checks=' . ale#Escape('*') . ' %s' \ . ' -p ' . ale#Escape('/foo/bar') - \ . ' -- -x c++' call ale#test#SetFilename('test.hpp') diff --git a/test/command_callback/test_dart_analysis_server_command_callback.vader b/test/command_callback/test_dart_analysis_server_command_callback.vader new file mode 100644 index 00000000..1754109a --- /dev/null +++ b/test/command_callback/test_dart_analysis_server_command_callback.vader @@ -0,0 +1,15 @@ +Before: + call ale#assert#SetUpLinterTest('dart', 'analysis_server') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct): + AssertLinter 'dart', ale#Escape('dart') + \ . ' ./snapshots/analysis_server.dart.snapshot --lsp' + +Execute(The executable should be configurable): + let g:ale_dart_analysis_server_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') + \ . ' ./snapshots/analysis_server.dart.snapshot --lsp' diff --git a/test/command_callback/test_elixir_credo.vader b/test/command_callback/test_elixir_credo.vader index 3eb88846..b14444c6 100644 --- a/test/command_callback/test_elixir_credo.vader +++ b/test/command_callback/test_elixir_credo.vader @@ -38,3 +38,10 @@ Execute(Builds credo command with suggest mode when set to 0): AssertLinter 'mix', \ ale#path#CdString(ale#path#Simplify(g:dir . '/elixir_paths/mix_project')) \ . 'mix help credo && mix credo suggest --format=flycheck --read-from-stdin %s' + +Execute(Builds credo command with a custom config file): + let g:ale_elixir_credo_config_file = '/home/user/custom_credo.exs' + + AssertLinter 'mix', + \ ale#path#CdString(ale#path#Simplify(g:dir . '/elixir_paths/mix_project')) + \ . 'mix help credo && mix credo suggest --config-file /home/user/custom_credo.exs --format=flycheck --read-from-stdin %s' diff --git a/test/command_callback/test_erlang_dialyzer_command_callback.vader b/test/command_callback/test_erlang_dialyzer_command_callback.vader index 5e21c053..5e818d7f 100644 --- a/test/command_callback/test_erlang_dialyzer_command_callback.vader +++ b/test/command_callback/test_erlang_dialyzer_command_callback.vader @@ -25,6 +25,14 @@ Execute(The command should accept configured executable.): \ . ' -Wunderspecs' \ . ' %s' +Execute(The command should accept configured options.): + let b:ale_erlang_dialyzer_options = '-r ' . expand('$HOME') + AssertLinter 'dialyzer', + \ ale#Escape('dialyzer') + \ . ' -n --plt ' . ale#Escape(expand('$HOME/.dialyzer_plt')) + \ . ' -r ' . expand('$HOME') + \ . ' %s' + Execute(The command should accept configured PLT file.): let b:ale_erlang_dialyzer_plt_file = 'custom-plt' AssertLinter 'dialyzer', diff --git a/test/command_callback/test_erlang_erlc_command_callback.vader b/test/command_callback/test_erlang_erlc_command_callback.vader new file mode 100644 index 00000000..7d659a07 --- /dev/null +++ b/test/command_callback/test_erlang_erlc_command_callback.vader @@ -0,0 +1,40 @@ +Before: + call ale#assert#SetUpLinterTest('erlang', 'erlc') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default command should be correct.): + let g:cmd = ale_linters#erlang#erlc#GetCommand(bufnr('')) + let g:regex = 'erlc.\+-o.\+%t' + let g:matched = match(g:cmd, g:regex) + + " match returns -1 if not found + AssertNotEqual + \ g:matched, + \ -1, + \ 'Command error: expected [' . g:cmd . '] to match [' . g:regex . ']' + +Execute(The command should accept configured executable.): + let b:ale_erlang_erlc_executable = '/usr/bin/erlc' + let g:cmd = ale_linters#erlang#erlc#GetCommand(bufnr('')) + let g:regex = '/usr/bin/erlc.\+-o.\+%t' + let g:matched = match(g:cmd, g:regex) + + " match returns -1 if not found + AssertNotEqual + \ g:matched, + \ -1, + \ 'Command error: expected [' . g:cmd . '] to match [' . g:regex . ']' + +Execute(The command should accept configured options.): + let b:ale_erlang_erlc_options = '-I include' + let g:cmd = ale_linters#erlang#erlc#GetCommand(bufnr('')) + let g:regex = 'erlc.\+-o.\+-I include.\+%t' + let g:matched = match(g:cmd, g:regex) + + " match returns -1 if not found + AssertNotEqual + \ g:matched, + \ -1, + \ 'Command error: expected [' . g:cmd . '] to match [' . g:regex . ']' diff --git a/test/command_callback/test_fecs_command_callback.vader b/test/command_callback/test_fecs_command_callback.vader index f70ad084..4287d324 100644 --- a/test/command_callback/test_fecs_command_callback.vader +++ b/test/command_callback/test_fecs_command_callback.vader @@ -1,5 +1,6 @@ Before: call ale#assert#SetUpLinterTest('javascript', 'fecs') + runtime autoload/ale/handlers/fecs.vim After: call ale#assert#TearDownLinterTest() diff --git a/test/command_callback/test_haskell_hls_callbacks.vader b/test/command_callback/test_haskell_hls_callbacks.vader new file mode 100644 index 00000000..e64aab6f --- /dev/null +++ b/test/command_callback/test_haskell_hls_callbacks.vader @@ -0,0 +1,27 @@ +Before: + call ale#assert#SetUpLinterTest('haskell', 'hls') + + Save &filetype + let &filetype = 'haskell' + +After: + call ale#assert#TearDownLinterTest() + +Execute(The language string should be correct): + AssertLSPLanguage 'haskell' + +Execute(The default executable should be correct): + AssertLinter 'haskell-language-server-wrapper', + \ ale#Escape('haskell-language-server-wrapper') . ' --lsp' + +Execute(The project root should be detected correctly): + AssertLSPProject g:dir + + call ale#test#SetFilename('hls_paths/file.hs') + + AssertLSPProject ale#path#Simplify(g:dir . '/hls_paths') + +Execute(The executable should be configurable): + let g:ale_haskell_hls_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') . ' --lsp' diff --git a/test/command_callback/test_ibm_openapi_validator_command_callback.vader b/test/command_callback/test_ibm_openapi_validator_command_callback.vader new file mode 100644 index 00000000..3484cc09 --- /dev/null +++ b/test/command_callback/test_ibm_openapi_validator_command_callback.vader @@ -0,0 +1,15 @@ +Before: + call ale#assert#SetUpLinterTest('openapi', 'ibm_validator') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The yaml ibm-openapi-validator command callback should return the correct default string): + AssertLinter 'lint-openapi', ale#Escape('lint-openapi') . ' %t' + +Execute(The yaml ibm-openapi-validator command callback should be configurable): + let g:ale_openapi_ibm_validator_executable = '~/.local/bin/lint-openapi' + let g:ale_openapi_ibm_validator_options = '-c ~/.config' + + AssertLinter '~/.local/bin/lint-openapi', ale#Escape('~/.local/bin/lint-openapi') + \ . ' -c ~/.config %t' diff --git a/test/command_callback/test_inko_inko_callbacks.vader b/test/command_callback/test_inko_inko_callbacks.vader new file mode 100644 index 00000000..93295c91 --- /dev/null +++ b/test/command_callback/test_inko_inko_callbacks.vader @@ -0,0 +1,20 @@ +Before: + call ale#assert#SetUpLinterTest('inko', 'inko') + call ale#test#SetFilename('inko_paths/test.inko') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The default executable path should be correct): + AssertLinter 'inko', ale#Escape('inko') . ' build --check --format=json %s' + +Execute(The inko callback should include tests/ for test paths): + call ale#engine#Cleanup(bufnr('')) + noautocmd e! inko_paths/tests/test/test_foo.inko + call ale#engine#InitBufferInfo(bufnr('')) + + AssertLinter 'inko', + \ ale#Escape('inko') + \ . ' build --check --format=json --include ' + \ . ale#Escape(ale#path#Simplify(g:dir . '/inko_paths/tests/')) + \ . ' %s' diff --git a/test/command_callback/test_julia_languageserver_callbacks.vader b/test/command_callback/test_julia_languageserver_callbacks.vader index 3bc46e3d..96df81f1 100644 --- a/test/command_callback/test_julia_languageserver_callbacks.vader +++ b/test/command_callback/test_julia_languageserver_callbacks.vader @@ -11,16 +11,16 @@ After: Execute(The default executable path should be correct): AssertLinter 'julia', \ ale#Escape('julia') . - \' --startup-file=no --history-file=no -e ' . - \ ale#Escape('using LanguageServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, false); server.runlinter = true; run(server);') + \' --project=@. --startup-file=no --history-file=no -e ' . + \ ale#Escape('using LanguageServer; using Pkg; import StaticLint; import SymbolServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, dirname(Pkg.Types.Context().env.project_file)); server.runlinter = true; run(server);') Execute(The executable should be configurable): let g:ale_julia_executable = 'julia-new' AssertLinter 'julia-new', \ ale#Escape('julia-new') . - \' --startup-file=no --history-file=no -e ' . - \ ale#Escape('using LanguageServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, false); server.runlinter = true; run(server);') + \' --project=@. --startup-file=no --history-file=no -e ' . + \ ale#Escape('using LanguageServer; using Pkg; import StaticLint; import SymbolServer; server = LanguageServer.LanguageServerInstance(isdefined(Base, :stdin) ? stdin : STDIN, isdefined(Base, :stdout) ? stdout : STDOUT, dirname(Pkg.Types.Context().env.project_file)); server.runlinter = true; run(server);') Execute(The project root should be detected correctly): AssertLSPProject '' diff --git a/test/command_callback/test_rust_analyzer_callbacks.vader b/test/command_callback/test_rust_analyzer_callbacks.vader index 95866076..efab1378 100644 --- a/test/command_callback/test_rust_analyzer_callbacks.vader +++ b/test/command_callback/test_rust_analyzer_callbacks.vader @@ -16,5 +16,5 @@ Execute(The project root should be detected correctly): Execute(Should accept configuration settings): AssertLSPConfig {} - let b:ale_rust_analyzer_config = {'rust': {'clippy_preference': 'on'}} - AssertLSPConfig {'rust': {'clippy_preference': 'on'}} + let b:ale_rust_analyzer_config = {'diagnostics': {'disabled': ['unresolved-import']}} + AssertLSPOptions {'diagnostics': {'disabled': ['unresolved-import']}} diff --git a/test/command_callback/test_sorbet_command_callback.vader b/test/command_callback/test_sorbet_command_callback.vader index b46e90a4..fe758635 100644 --- a/test/command_callback/test_sorbet_command_callback.vader +++ b/test/command_callback/test_sorbet_command_callback.vader @@ -5,6 +5,7 @@ Before: let g:ale_ruby_sorbet_executable = 'srb' let g:ale_ruby_sorbet_options = '' + let g:ale_ruby_sorbet_enable_watchman = 0 After: call ale#assert#TearDownLinterTest() @@ -13,6 +14,12 @@ Execute(Executable should default to srb): AssertLinter 'srb', ale#Escape('srb') \ . ' tc --lsp --disable-watchman' +Execute(Able to enable watchman): + let g:ale_ruby_sorbet_enable_watchman = 1 + + AssertLinter 'srb', ale#Escape('srb') + \ . ' tc --lsp' + Execute(Should be able to set a custom executable): let g:ale_ruby_sorbet_executable = 'bin/srb' diff --git a/test/command_callback/test_spectral_command_callback.vader b/test/command_callback/test_spectral_command_callback.vader new file mode 100644 index 00000000..ed3795b9 --- /dev/null +++ b/test/command_callback/test_spectral_command_callback.vader @@ -0,0 +1,31 @@ +Before: + call ale#assert#SetUpLinterTest('yaml', 'spectral') + +After: + call ale#assert#TearDownLinterTest() + +Execute(The yaml spectral command callback should return the correct default string): + AssertLinter 'spectral', ale#Escape('spectral') . ' lint --ignore-unknown-format -q -f text %t' + +Execute(The yaml spectral command callback should be configurable): + let g:ale_yaml_spectral_executable = '~/.local/bin/spectral' + + AssertLinter '~/.local/bin/spectral', + \ ale#Escape('~/.local/bin/spectral') + \ . ' lint --ignore-unknown-format -q -f text %t' + +Execute(The yaml spectral command callback should allow a global installation to be used): + let g:ale_yaml_spectral_executable = '/usr/local/bin/spectral' + let g:ale_yaml_spectral_use_global = 1 + + AssertLinter '/usr/local/bin/spectral', + \ ale#Escape('/usr/local/bin/spectral') + \ . ' lint --ignore-unknown-format -q -f text %t' + +Execute(The yaml spectral command callback should allow a local installation to be used): + call ale#test#SetFilename('spectral_paths/openapi.yaml') + + AssertLinter + \ ale#path#Simplify(g:dir . '/spectral_paths/node_modules/.bin/spectral'), + \ ale#Escape(ale#path#Simplify(g:dir . '/spectral_paths/node_modules/.bin/spectral')) + \ . ' lint --ignore-unknown-format -q -f text %t' diff --git a/test/command_callback/test_terraform_ls_command_callback.vader b/test/command_callback/test_terraform_ls_command_callback.vader new file mode 100644 index 00000000..d559ba8c --- /dev/null +++ b/test/command_callback/test_terraform_ls_command_callback.vader @@ -0,0 +1,61 @@ +Before: + call ale#assert#SetUpLinterTest('terraform', 'terraform_ls') + +After: + if isdirectory(g:dir . '/.terraform') + call delete(g:dir . '/.terraform', 'd') + endif + + unlet! b:ale_terraform_terraform_executable + unlet! b:ale_terraform_ls_executable + unlet! b:ale_terraform_ls_options + + call ale#assert#TearDownLinterTest() + +Execute(Should send correct LSP language): + AssertLSPLanguage 'terraform' + +Execute(Should load default executable): + AssertLinter 'terraform-ls', + \ ale#Escape('terraform-ls') . ' serve' + +Execute(Should configure custom executable): + let b:ale_terraform_ls_executable = 'foo' + AssertLinter 'foo', + \ ale#Escape('foo') . ' serve' + +Execute(Should ignore non-absolute custom terraform executable): + let b:ale_terraform_terraform_executable = 'terraform' + AssertLinter 'terraform-ls', + \ ale#Escape('terraform-ls') . ' serve' + +Execute(Should set absolute custom terraform executable): + let b:ale_terraform_terraform_executable = '/bin/terraform' + AssertLinter 'terraform-ls', + \ ale#Escape('terraform-ls') . ' serve -tf-exec /bin/terraform' + +Execute(Should set custom options): + let b:ale_terraform_ls_options = '--bar' + + AssertLinter 'terraform-ls', + \ ale#Escape('terraform-ls') . ' serve --bar' + +Execute(Should return current directory if it contains .terraform directory): + call mkdir(g:dir . '/.terraform') + AssertLSPProject g:dir + +Execute(Should return nearest directory with .terraform if found in parent directory): + call ale#test#SetFilename('../terraform_files/main.tf') + + let b:parent_dir = ale#path#Simplify(g:dir . '/..') + let b:tf_dir = b:parent_dir . '/.terraform' + + if !isdirectory(b:tf_dir) + call mkdir(b:tf_dir) + endif + + AssertLSPProject b:parent_dir + + call delete(b:tf_dir, 'd') + unlet!b:parent_dir + unlet!b:tf_dir diff --git a/test/command_callback/test_terraform_terraform_command_callback.vader b/test/command_callback/test_terraform_terraform_command_callback.vader index fabd902d..25ca652a 100644 --- a/test/command_callback/test_terraform_terraform_command_callback.vader +++ b/test/command_callback/test_terraform_terraform_command_callback.vader @@ -6,4 +6,10 @@ After: call ale#assert#TearDownLinterTest() Execute(The default command should be correct): - AssertLinter 'terraform', ale#Escape('terraform') . ' fmt -no-color --check=true -' + AssertLinter 'terraform', + \ ale#Escape('terraform') . ' validate -no-color -json ' + +Execute(The default command should be overriden): + let b:ale_terraform_terraform_executable = '/bin/other/terraform' + AssertLinter '/bin/other/terraform', + \ ale#Escape('/bin/other/terraform') . ' validate -no-color -json ' diff --git a/test/command_callback/test_typescript_deno_lsp.vader b/test/command_callback/test_typescript_deno_lsp.vader new file mode 100644 index 00000000..01cbc851 --- /dev/null +++ b/test/command_callback/test_typescript_deno_lsp.vader @@ -0,0 +1,60 @@ +Before: + let g:ale_deno_unstable = 0 + let g:ale_deno_executable = 'deno' + let g:ale_deno_project_root = '' + + runtime autoload/ale/handlers/deno.vim + call ale#assert#SetUpLinterTest('typescript', 'deno') + +After: + call ale#assert#TearDownLinterTest() + +Execute(Should set deno lsp for TypeScript projects using stable Deno API): + AssertLSPLanguage 'typescript' + AssertLSPConfig {} + AssertLSPProject ale#path#Simplify(g:dir . '/../..') + AssertLSPOptions { + \ 'enable': v:true, + \ 'lint': v:true, + \ 'unstable': v:false + \} + +Execute(Should set deno lsp using unstable Deno API if enabled by user): + let g:ale_deno_unstable = 1 + AssertLSPLanguage 'typescript' + AssertLSPConfig {} + AssertLSPProject ale#path#Simplify(g:dir . '/../..') + AssertLSPOptions { + \ 'enable': v:true, + \ 'lint': v:true, + \ 'unstable': v:true + \} + +Execute(Should find project root containing tsconfig.json): + call ale#test#SetFilename('../typescript/test.ts') + AssertLSPLanguage 'typescript' + AssertLSPConfig {} + AssertLSPProject ale#path#Simplify(g:dir . '/../typescript') + AssertLSPOptions { + \ 'enable': v:true, + \ 'lint': v:true, + \ 'unstable': v:false + \} + +Execute(Should use user-specified project root): + let g:ale_deno_lsp_project_root = '/' + + call ale#test#SetFilename('../typescript/test.ts') + AssertLSPLanguage 'typescript' + AssertLSPConfig {} + AssertLSPProject '/' + AssertLSPOptions { + \ 'enable': v:true, + \ 'lint': v:true, + \ 'unstable': v:false + \} + +Execute(Check Deno LSP command): + AssertLinter 'deno', [ + \ ale#Escape('deno') . ' lsp', + \] diff --git a/test/command_callback/test_xo_command_callback.vader b/test/command_callback/test_xo_command_callback.vader index 65cb4f8a..1aa4c3f1 100644 --- a/test/command_callback/test_xo_command_callback.vader +++ b/test/command_callback/test_xo_command_callback.vader @@ -1,8 +1,11 @@ Before: - call ale#assert#SetUpLinterTest('typescript', 'xo') - call ale#test#SetFilename('testfile.ts') + call ale#assert#SetUpLinterTest('javascript', 'xo') + call ale#test#SetFilename('testfile.jsx') unlet! b:executable + set filetype=javascriptreact + runtime autoload/ale/handlers/xo.vim + After: call ale#assert#TearDownLinterTest() @@ -10,11 +13,11 @@ Execute(The XO executable should be called): AssertLinter 'xo', ale#Escape('xo') . ' --reporter json --stdin --stdin-filename %s' Execute(The XO executable should be configurable): - let b:ale_typescript_xo_executable = 'foobar' + let b:ale_javascript_xo_executable = 'foobar' AssertLinter 'foobar', ale#Escape('foobar') . ' --reporter json --stdin --stdin-filename %s' Execute(The XO options should be configurable): - let b:ale_typescript_xo_options = '--wat' + let b:ale_javascript_xo_options = '--wat' AssertLinter 'xo', ale#Escape('xo') . ' --wat --reporter json --stdin --stdin-filename %s' diff --git a/test/command_callback/test_xots_command_callback.vader b/test/command_callback/test_xots_command_callback.vader new file mode 100644 index 00000000..cc38ff02 --- /dev/null +++ b/test/command_callback/test_xots_command_callback.vader @@ -0,0 +1,23 @@ +Before: + call ale#assert#SetUpLinterTest('typescript', 'xo') + call ale#test#SetFilename('testfile.tsx') + unlet! b:executable + + set filetype=typescriptreact + runtime autoload/ale/handlers/xo.vim + +After: + call ale#assert#TearDownLinterTest() + +Execute(The XO executable should be called): + AssertLinter 'xo', ale#Escape('xo') . ' --reporter json --stdin --stdin-filename %s' + +Execute(The XO executable should be configurable): + let b:ale_typescript_xo_executable = 'foobar' + + AssertLinter 'foobar', ale#Escape('foobar') . ' --reporter json --stdin --stdin-filename %s' + +Execute(The XO options should be configurable): + let b:ale_typescript_xo_options = '--wat' + + AssertLinter 'xo', ale#Escape('xo') . ' --wat --reporter json --stdin --stdin-filename %s' diff --git a/test/completion/test_lsp_completion_parsing.vader b/test/completion/test_lsp_completion_parsing.vader index 36228c10..a334d945 100644 --- a/test/completion/test_lsp_completion_parsing.vader +++ b/test/completion/test_lsp_completion_parsing.vader @@ -10,37 +10,39 @@ After: unlet! b:ale_completion_info Execute(Should handle Rust completion results correctly): + let g:ale_completion_autoimport = 0 + AssertEqual \ [ - \ {'word': 'new', 'menu': 'pub fn new() -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'with_capacity', 'menu': 'pub fn with_capacity(capacity: usize) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'from_utf8', 'menu': 'pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error>', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'from_utf8_lossy', 'menu': 'pub fn from_utf8_lossy<''a>(v: &''a [u8]) -> Cow<''a, str>', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'from_utf16', 'menu': 'pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error>', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'from_utf16_lossy', 'menu': 'pub fn from_utf16_lossy(v: &[u16]) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'from_raw_parts', 'menu': 'pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'from_utf8_unchecked', 'menu': 'pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = &''a char>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = &''a str>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'from_iter', 'menu': 'fn from_iter<I: IntoIterator<Item = Cow<''a, str>>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'Searcher', 'menu': 'type Searcher = <&''b str as Pattern<''a>>::Searcher;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'default', 'menu': 'fn default() -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'Output', 'menu': 'type Output = String;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'Output', 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'Target', 'menu': 'type Target = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'Err', 'menu': 'type Err = ParseError;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'from_str', 'menu': 'fn from_str(s: &str) -> Result<String, ParseError>', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'from', 'menu': 'fn from(s: &''a str) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'from', 'menu': 'fn from(s: Box<str>) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'from', 'menu': 'fn from(s: Cow<''a, str>) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'to_vec', 'menu': 'pub fn to_vec(&self) -> Vec<T> where T: Clone,', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'new', 'dup': 0, 'menu': 'pub fn new() -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'with_capacity', 'dup': 0, 'menu': 'pub fn with_capacity(capacity: usize) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'from_utf8', 'dup': 0, 'menu': 'pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error>', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'from_utf8_lossy', 'dup': 0, 'menu': 'pub fn from_utf8_lossy<''a>(v: &''a [u8]) -> Cow<''a, str>', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'from_utf16', 'dup': 0, 'menu': 'pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error>', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'from_utf16_lossy', 'dup': 0, 'menu': 'pub fn from_utf16_lossy(v: &[u16]) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'from_raw_parts', 'dup': 0, 'menu': 'pub unsafe fn from_raw_parts(buf: *mut u8, length: usize, capacity: usize) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'from_utf8_unchecked', 'dup': 0, 'menu': 'pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'from_iter', 'dup': 0, 'menu': 'fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'from_iter', 'dup': 0, 'menu': 'fn from_iter<I: IntoIterator<Item = &''a char>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'from_iter', 'dup': 0, 'menu': 'fn from_iter<I: IntoIterator<Item = &''a str>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'from_iter', 'dup': 0, 'menu': 'fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'from_iter', 'dup': 0, 'menu': 'fn from_iter<I: IntoIterator<Item = Cow<''a, str>>>(iter: I) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'Searcher', 'dup': 0, 'menu': 'type Searcher = <&''b str as Pattern<''a>>::Searcher;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'default', 'dup': 0, 'menu': 'fn default() -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'Output', 'dup': 0, 'menu': 'type Output = String;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'Output', 'dup': 0, 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'Output', 'dup': 0, 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'Output', 'dup': 0, 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'Output', 'dup': 0, 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'Output', 'dup': 0, 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'Output', 'dup': 0, 'menu': 'type Output = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'Target', 'dup': 0, 'menu': 'type Target = str;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'Err', 'dup': 0, 'menu': 'type Err = ParseError;', 'info': '', 'kind': 't', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'from_str', 'dup': 0, 'menu': 'fn from_str(s: &str) -> Result<String, ParseError>', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'from', 'dup': 0, 'menu': 'fn from(s: &''a str) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'from', 'dup': 0, 'menu': 'fn from(s: Box<str>) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'from', 'dup': 0, 'menu': 'fn from(s: Cow<''a, str>) -> String', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'to_vec', 'dup': 0, 'menu': 'pub fn to_vec(&self) -> Vec<T> where T: Clone,', 'info': '', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, \], \ ale#completion#ParseLSPCompletions({ \ "jsonrpc":"2.0", @@ -195,13 +197,14 @@ Execute(Should handle Rust completion results correctly): \ }) Execute(Should handle Python completion results correctly): + let g:ale_completion_autoimport = 0 let b:ale_completion_info = { \ 'completion_filter': 'ale#completion#python#CompletionItemFilter', \} AssertEqual \ [ - \ {'word': 'what', 'menu': 'example-python-project.bar.Bar', 'info': "what()\n\n", 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'what', 'dup': 0, 'menu': 'example-python-project.bar.Bar', 'info': "what()\n\n", 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, \ ], \ ale#completion#ParseLSPCompletions({ \ "jsonrpc":"2.0", @@ -406,6 +409,8 @@ Execute(Should handle Python completion results correctly): \ }) Execute(Should handle extra Python completion results correctly): + let g:ale_completion_autoimport = 0 + let b:ale_completion_info = { \ 'completion_filter': 'ale#completion#python#CompletionItemFilter', \ 'prefix': 'mig', @@ -413,8 +418,8 @@ Execute(Should handle extra Python completion results correctly): AssertEqual \ [ - \ {'word': 'migrations', 'menu': 'xxx', 'info': 'migrations', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, - \ {'word': 'MigEngine', 'menu': 'xxx', 'info': 'mig engine', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'migrations', 'dup': 0, 'menu': 'xxx', 'info': 'migrations', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'MigEngine', 'dup': 0, 'menu': 'xxx', 'info': 'mig engine', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, \ ], \ ale#completion#ParseLSPCompletions({ \ 'jsonrpc': '2.0', @@ -445,9 +450,11 @@ Execute(Should handle extra Python completion results correctly): \ }) Execute(Should handle missing keys): + let g:ale_completion_autoimport = 0 + AssertEqual \ [ - \ {'word': 'x', 'menu': '', 'info': '', 'kind': 'v', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'x', 'dup': 0, 'menu': '', 'info': '', 'kind': 'v', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, \ ], \ ale#completion#ParseLSPCompletions({ \ 'jsonrpc': '2.0', @@ -463,9 +470,11 @@ Execute(Should handle missing keys): \ }) Execute(Should handle documentation in the markdown format): + let g:ale_completion_autoimport = 0 + AssertEqual \ [ - \ {'word': 'migrations', 'menu': 'xxx', 'info': 'Markdown documentation', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'migrations', 'dup': 0, 'menu': 'xxx', 'info': 'Markdown documentation', 'kind': 'f', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, \ ], \ ale#completion#ParseLSPCompletions({ \ 'jsonrpc': '2.0', @@ -487,9 +496,11 @@ Execute(Should handle documentation in the markdown format): \ }) Execute(Should handle completion messages with textEdit objects): + let g:ale_completion_autoimport = 0 + AssertEqual \ [ - \ {'word': 'next_callback', 'menu': 'PlayTimeCallback', 'info': '', 'kind': 'v', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'next_callback', 'dup': 0, 'menu': 'PlayTimeCallback', 'info': '', 'kind': 'v', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, \ ], \ ale#completion#ParseLSPCompletions({ \ 'id': 226, @@ -518,9 +529,11 @@ Execute(Should handle completion messages with textEdit objects): \ }) Execute(Should handle completion messages with the deprecated insertText attribute): + let g:ale_completion_autoimport = 0 + AssertEqual \ [ - \ {'word': 'next_callback', 'menu': 'PlayTimeCallback', 'info': '', 'kind': 'v', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, + \ {'word': 'next_callback', 'dup': 0, 'menu': 'PlayTimeCallback', 'info': '', 'kind': 'v', 'icase': 1, 'user_data': json_encode({'_ale_completion_item': 1})}, \ ], \ ale#completion#ParseLSPCompletions({ \ 'id': 226, @@ -548,6 +561,7 @@ Execute(Should handle completion messages with additionalTextEdits when ale_comp \ [ \ { \ 'word': 'next_callback', + \ 'dup': 1, \ 'menu': 'PlayTimeCallback', \ 'info': '', \ 'kind': 'v', @@ -661,6 +675,7 @@ Execute(Should still handle completion messages with empty additionalTextEdits w \ [ \ { \ 'word': 'next_callback', + \ 'dup': 0, \ 'menu': 'PlayTimeCallback', \ 'info': '', \ 'kind': 'v', diff --git a/test/completion/test_omnifunc_completion.vader b/test/completion/test_omnifunc_completion.vader index 3711f974..1db64705 100644 --- a/test/completion/test_omnifunc_completion.vader +++ b/test/completion/test_omnifunc_completion.vader @@ -45,15 +45,15 @@ Execute(The start position should be returned when results can be requested): AssertEqual 11, ale#completion#OmniFunc(1, '') Execute(The omnifunc function should return async results): - " Neovim 0.2.0 struggles at running these tests. - if !has('nvim') || has('nvim-0.3.0') + " Neovim 0.2.0 and 0.4.4 struggles at running these tests. + if !has('nvim') call timer_start(0, function('SetCompletionResult')) AssertEqual ['foo'], ale#completion#OmniFunc(0, '') endif Execute(The omnifunc function should parse and return async responses): - if !has('nvim') || has('nvim-0.3.0') + if !has('nvim') call timer_start(0, function('SetCompletionResponse')) AssertEqual ['foo'], ale#completion#OmniFunc(0, '') diff --git a/test/dumb_named_pipe_server.py b/test/dumb_named_pipe_server.py new file mode 100644 index 00000000..a77e538c --- /dev/null +++ b/test/dumb_named_pipe_server.py @@ -0,0 +1,42 @@ +""" +This Python script creates a named pipe server that does nothing but send its input +back to the client that connects to it. Only one argument must be given, the path +of a named pipe to bind to. +""" +import os +import socket +import sys + + +def main(): + if len(sys.argv) < 2: + sys.exit('You must specify a filepath') + + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + if os.path.exists(sys.argv[1]): + os.remove(sys.argv[1]) + sock.bind(sys.argv[1]) + sock.listen(0) + + pid = os.fork() + + if pid: + print(pid) + sys.exit() + + while True: + connection = sock.accept()[0] + connection.settimeout(5) + + while True: + try: + connection.send(connection.recv(1024)) + except socket.timeout: + break + + connection.close() + + +if __name__ == "__main__": + main() diff --git a/test/eslint-test-files/react-app/node_modules/xo/cli.js b/test/eslint-test-files/react-app/node_modules/xo/cli.js new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/eslint-test-files/react-app/node_modules/xo/cli.js diff --git a/test/eslint-test-files/react-app/subdir/testfile.ts b/test/eslint-test-files/react-app/subdir/testfile.ts new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/eslint-test-files/react-app/subdir/testfile.ts diff --git a/test/fixers/test_dhall_fixer_callback.vader b/test/fixers/test_dhall_fixer_callback.vader deleted file mode 100644 index f27880b7..00000000 --- a/test/fixers/test_dhall_fixer_callback.vader +++ /dev/null @@ -1,11 +0,0 @@ -Before: - call ale#assert#SetUpFixerTest('dhall', 'dhall') - -After: - call ale#assert#TearDownFixerTest() - -Execute(The default command should be correct): - AssertFixer - \ { 'read_temporary_file': 1, - \ 'command': ale#Escape('dhall') . ' format --inplace %t' - \ } diff --git a/test/fixers/test_dhall_format_fixer_callback.vader b/test/fixers/test_dhall_format_fixer_callback.vader new file mode 100644 index 00000000..9bc17f7e --- /dev/null +++ b/test/fixers/test_dhall_format_fixer_callback.vader @@ -0,0 +1,24 @@ +Before: + Save g:ale_dhall_executable + Save g:ale_dhall_options + + " Use an invalid global executable, so we don’t match it. + let g:ale_dhall_executable = 'odd-dhall' + let g:ale_dhall_options = '--ascii' + + call ale#assert#SetUpFixerTest('dhall-format', 'dhall-format') + +After: + call ale#assert#TearDownFixerTest() + +Execute(The dhall-format callback should return the correct options): + call ale#test#SetFilename('../dhall_files/testfile.dhall') + + AssertFixer + \ { + \ 'command': ale#Escape('odd-dhall') + \ . ' --ascii' + \ . ' format' + \ . ' --inplace %t', + \ 'read_temporary_file': 1, + \ } diff --git a/test/fixers/test_dhall_freeze_fixer_callback.vader b/test/fixers/test_dhall_freeze_fixer_callback.vader new file mode 100644 index 00000000..c8f820bb --- /dev/null +++ b/test/fixers/test_dhall_freeze_fixer_callback.vader @@ -0,0 +1,24 @@ +Before: + Save g:ale_dhall_executable + Save g:ale_dhall_options + + " Use an invalid global executable, so we don’t match it. + let g:ale_dhall_executable = 'odd-dhall' + let g:ale_dhall_options = '--ascii' + let g:ale_dhall_freeze_options = '--all' + + call ale#assert#SetUpFixerTest('dhall-freeze', 'dhall-freeze') + +After: + call ale#assert#TearDownFixerTest() + +Execute(The dhall-freeze callback should return the correct options): + AssertFixer + \ { + \ 'command': ale#Escape('odd-dhall') + \ . ' --ascii' + \ . ' freeze' + \ . ' --all' + \ . ' --inplace %t', + \ 'read_temporary_file': 1, + \ } diff --git a/test/fixers/test_dhall_lint_fixer_callback.vader b/test/fixers/test_dhall_lint_fixer_callback.vader new file mode 100644 index 00000000..82229363 --- /dev/null +++ b/test/fixers/test_dhall_lint_fixer_callback.vader @@ -0,0 +1,22 @@ +Before: + Save g:ale_dhall_executable + Save g:ale_dhall_options + + " Use an invalid global executable, so we don’t match it. + let g:ale_dhall_executable = 'odd-dhall' + let g:ale_dhall_options = '--ascii' + + call ale#assert#SetUpFixerTest('dhall-lint', 'dhall-lint') + +After: + call ale#assert#TearDownFixerTest() + +Execute(The dhall-lint callback should return the correct options): + AssertFixer + \ { + \ 'command': ale#Escape('odd-dhall') + \ . ' --ascii' + \ . ' lint' + \ . ' --inplace %t', + \ 'read_temporary_file': 1, + \ } diff --git a/test/fixers/test_isort_fixer_callback.vader b/test/fixers/test_isort_fixer_callback.vader index 7f389dcf..3941f6dd 100644 --- a/test/fixers/test_isort_fixer_callback.vader +++ b/test/fixers/test_isort_fixer_callback.vader @@ -5,6 +5,7 @@ Before: " Use an invalid global executable, so we don't match it. let g:ale_python_isort_executable = 'xxxinvalid' let g:ale_python_isort_options = '' + let g:ale_python_isort_auto_pipenv = 0 call ale#test#SetDirectory('/testplugin/test/fixers') silent cd .. @@ -48,3 +49,12 @@ Execute(The isort callback should respect custom options): \ . ' --multi-line=3 --trailing-comma -', \ }, \ ale#fixers#isort#Fix(bufnr('')) + +Execute(Pipenv is detected when python_isort_auto_pipenv is set): + let g:ale_python_isort_auto_pipenv = 1 + + call ale#test#SetFilename('/testplugin/test/python_fixtures/pipenv/whatever.py') + + AssertEqual + \ {'command': ale#path#BufferCdString(bufnr('')) . ale#Escape('pipenv') . ' run isort -'}, + \ ale#fixers#isort#Fix(bufnr('')) diff --git a/test/fixers/test_standardrb_fixer_callback.vader b/test/fixers/test_standardrb_fixer_callback.vader index 99234b79..d315651f 100644 --- a/test/fixers/test_standardrb_fixer_callback.vader +++ b/test/fixers/test_standardrb_fixer_callback.vader @@ -21,9 +21,9 @@ Execute(The standardrb callback should return the correct default values): AssertEqual \ { - \ 'read_temporary_file': 1, + \ 'process_with': 'ale#fixers#rubocop#PostProcess', \ 'command': ale#Escape(g:ale_ruby_standardrb_executable) - \ . ' --fix --force-exclusion %t', + \ . ' --fix --force-exclusion --stdin %s', \ }, \ ale#fixers#standardrb#Fix(bufnr('')) @@ -32,10 +32,10 @@ Execute(The standardrb callback should include configuration files): AssertEqual \ { - \ 'read_temporary_file': 1, + \ 'process_with': 'ale#fixers#rubocop#PostProcess', \ 'command': ale#Escape(g:ale_ruby_standardrb_executable) \ . ' --config ' . ale#Escape(ale#path#Simplify(g:dir . '/ruby_paths/with_config/.standard.yml')) - \ . ' --fix --force-exclusion %t', + \ . ' --fix --force-exclusion --stdin %s', \ }, \ ale#fixers#standardrb#Fix(bufnr('')) @@ -45,10 +45,10 @@ Execute(The standardrb callback should include custom rubocop options): AssertEqual \ { - \ 'read_temporary_file': 1, + \ 'process_with': 'ale#fixers#rubocop#PostProcess', \ 'command': ale#Escape(g:ale_ruby_standardrb_executable) \ . ' --config ' . ale#Escape(ale#path#Simplify(g:dir . '/ruby_paths/with_config/.standard.yml')) \ . ' --except Lint/Debugger' - \ . ' --fix --force-exclusion %t', + \ . ' --fix --force-exclusion --stdin %s', \ }, \ ale#fixers#standardrb#Fix(bufnr('')) diff --git a/test/fixers/test_xo_fixer_callback.vader b/test/fixers/test_xo_fixer_callback.vader new file mode 100644 index 00000000..a473606e --- /dev/null +++ b/test/fixers/test_xo_fixer_callback.vader @@ -0,0 +1,45 @@ +Before: + call ale#assert#SetUpFixerTest('javascript', 'xo') + runtime autoload/ale/handlers/xo.vim + set filetype=javascript + +After: + call ale#assert#TearDownFixerTest() + +Execute(The xo callback should return the correct default values): + call ale#test#SetFilename('../xo-test-files/monorepo/packages/a/index.js') + + AssertFixer + \ { + \ 'read_temporary_file': 1, + \ 'command': (has('win32') ? 'node.exe ' : '') + \ . ale#Escape(ale#path#Simplify(g:dir . '/../xo-test-files/monorepo/node_modules/xo/cli.js')) + \ . ' --fix %t', + \ } + +Execute(The xo callback should include custom xo options): + let g:ale_javascript_xo_options = '--space' + call ale#test#SetFilename('../xo-test-files/monorepo/packages/a/index.js') + + AssertFixer + \ { + \ 'read_temporary_file': 1, + \ 'command': (has('win32') ? 'node.exe ' : '') + \ . ale#Escape(ale#path#Simplify(g:dir . '/../xo-test-files/monorepo/node_modules/xo/cli.js')) + \ . ' --fix %t' + \ . ' --space', + \ } + +Execute(--stdin should be used when xo is new enough): + let g:ale_javascript_xo_options = '--space' + call ale#test#SetFilename('../xo-test-files/monorepo/packages/a/index.js') + + GivenCommandOutput ['0.30.0'] + AssertFixer + \ { + \ 'command': (has('win32') ? 'node.exe ' : '') + \ . ale#Escape(ale#path#Simplify(g:dir . '/../xo-test-files/monorepo/node_modules/xo/cli.js')) + \ . ' --stdin --stdin-filename %s' + \ . ' --fix' + \ . ' --space', + \ } diff --git a/test/fixers/test_xots_fixer_callback.vader b/test/fixers/test_xots_fixer_callback.vader new file mode 100644 index 00000000..5c7fa1d1 --- /dev/null +++ b/test/fixers/test_xots_fixer_callback.vader @@ -0,0 +1,45 @@ +Before: + call ale#assert#SetUpFixerTest('typescript', 'xo') + runtime autoload/ale/handlers/xo.vim + set filetype=typescript + +After: + call ale#assert#TearDownFixerTest() + +Execute(The xo callback should return the correct default values): + call ale#test#SetFilename('../xo-test-files/monorepo/packages/a/index.ts') + + AssertFixer + \ { + \ 'read_temporary_file': 1, + \ 'command': (has('win32') ? 'node.exe ' : '') + \ . ale#Escape(ale#path#Simplify(g:dir . '/../xo-test-files/monorepo/node_modules/xo/cli.js')) + \ . ' --fix %t', + \ } + +Execute(The xo callback should include custom xo options): + let g:ale_typescript_xo_options = '--space' + call ale#test#SetFilename('../xo-test-files/monorepo/packages/a/index.ts') + + AssertFixer + \ { + \ 'read_temporary_file': 1, + \ 'command': (has('win32') ? 'node.exe ' : '') + \ . ale#Escape(ale#path#Simplify(g:dir . '/../xo-test-files/monorepo/node_modules/xo/cli.js')) + \ . ' --fix %t' + \ . ' --space', + \ } + +Execute(--stdin should be used when xo is new enough): + let g:ale_typescript_xo_options = '--space' + call ale#test#SetFilename('../xo-test-files/monorepo/packages/a/index.ts') + + GivenCommandOutput ['0.30.0'] + AssertFixer + \ { + \ 'command': (has('win32') ? 'node.exe ' : '') + \ . ale#Escape(ale#path#Simplify(g:dir . '/../xo-test-files/monorepo/node_modules/xo/cli.js')) + \ . ' --stdin --stdin-filename %s' + \ . ' --fix' + \ . ' --space', + \ } diff --git a/test/handler/test_atools_handler.vader b/test/handler/test_atools_handler.vader new file mode 100644 index 00000000..1bb9ca00 --- /dev/null +++ b/test/handler/test_atools_handler.vader @@ -0,0 +1,85 @@ +Before: + runtime autoload/ale/handlers/atools.vim + +After: + call ale#linter#Reset() + +Execute(The atools handler should handle basic errors or warings): + AssertEqual + \ [ + \ { + \ 'lnum': 2, + \ 'text': 'trailing whitespace', + \ 'type': 'E', + \ 'code': 'AL8', + \ }, + \ { + \ 'lnum': 15, + \ 'text': '$pkgname should not be used in the source url', + \ 'type': 'W', + \ 'code': 'AL29', + \ }, + \ ], + \ ale#handlers#atools#Handle(bufnr(''), [ + \ 'IC:[AL8]:APKBUILD:2:trailing whitespace', + \ 'MC:[AL29]:APKBUILD:15:$pkgname should not be used in the source url', + \ ]) + +" Regardless of the severity, if the certainty is [P]ossible and not [C]ertain +" or if regardless of the Certainity the Severity is not [I]mportant or [S]erious +" then it must be a [W]arning +Execute(If we are not Certain or Importantly Serious, be a Warning): + AssertEqual + \ [ + \ { + \ 'lnum': 3, + \ 'text': 'This violation is Serious but Possible false positive, I am a Warning!', + \ 'type': 'W', + \ 'code': 'AL', + \ }, + \ { + \ 'lnum': 4, + \ 'text': 'This violation is Important but Possible false positive, I am a Warning!', + \ 'type': 'W', + \ 'code': 'AL', + \ }, + \ { + \ 'lnum': 5, + \ 'text': 'This violation is Minor, I am a Warning!', + \ 'type': 'W', + \ 'code': 'AL', + \ }, + \ { + \ 'lnum': 6, + \ 'text': 'This violation is Style, I am a Warning!', + \ 'type': 'W', + \ 'code': 'AL', + \ }, + \ ], + \ ale#handlers#atools#Handle(bufnr(''), [ + \ 'SP:[AL]:APKBUILD:3:This violation is Serious but Possible false positive, I am a Warning!', + \ 'IP:[AL]:APKBUILD:4:This violation is Important but Possible false positive, I am a Warning!', + \ 'MC:[AL]:APKBUILD:5:This violation is Minor, I am a Warning!', + \ 'TC:[AL]:APKBUILD:6:This violation is Style, I am a Warning!', + \ ]) + +Execute(We should be error if we are Certain it is Serious or Important): + AssertEqual + \ [ + \ { + \ 'lnum': 7, + \ 'text': 'This is Certainly Serious, I am an Error!', + \ 'type': 'E', + \ 'code': 'AL', + \ }, + \ { + \ 'lnum': 8, + \ 'text': 'This is Certainly Important, I am an Error!', + \ 'type': 'E', + \ 'code': 'AL', + \ }, + \ ], + \ ale#handlers#atools#Handle(bufnr(''), [ + \ 'SC:[AL]:APKBUILD:7:This is Certainly Serious, I am an Error!', + \ 'IC:[AL]:APKBUILD:8:This is Certainly Important, I am an Error!', + \ ]) diff --git a/test/handler/test_dafny_handler.vader b/test/handler/test_dafny_handler.vader index 674f691d..4ca288d2 100644 --- a/test/handler/test_dafny_handler.vader +++ b/test/handler/test_dafny_handler.vader @@ -8,21 +8,29 @@ Execute(The Dafny handler should parse output correctly): AssertEqual \ [ \ { - \ 'bufnr': 0, + \ 'filename': 'File.dfy', \ 'col': 45, \ 'lnum': 123, \ 'text': 'A precondition for this call might not hold.', \ 'type': 'E' \ }, \ { - \ 'bufnr': 0, + \ 'filename': 'File.dfy', \ 'col': 90, \ 'lnum': 678, \ 'text': 'This is the precondition that might not hold.', \ 'type': 'W' - \ } + \ }, + \ { + \ 'filename': 'File.dfy', + \ 'col': 45, + \ 'lnum': 123, + \ 'text': "Verification of 'Impl$$_22_Proof.__default.PutKeepsMapsFull' timed out after 2 seconds", + \ 'type': 'E' + \ }, \ ], \ ale_linters#dafny#dafny#Handle(0, [ \ 'File.dfy(123,45): Error BP5002: A precondition for this call might not hold.', - \ 'File.dfy(678,90): Related location: This is the precondition that might not hold.' + \ 'File.dfy(678,90): Related location: This is the precondition that might not hold.', + \ "File.dfy(123,45): Verification of 'Impl$$_22_Proof.__default.PutKeepsMapsFull' timed out after 2 seconds", \ ]) diff --git a/test/handler/test_ibm_openapi_validator_handler.vader b/test/handler/test_ibm_openapi_validator_handler.vader new file mode 100644 index 00000000..e136d5d2 --- /dev/null +++ b/test/handler/test_ibm_openapi_validator_handler.vader @@ -0,0 +1,49 @@ +Before: + runtime! ale_linters/openapi/ibm_validator.vim + +After: + call ale#linter#Reset() + +Execute(Problems should be parsed correctly for openapi-ibm-validator): + AssertEqual + \ [ + \ { + \ 'lnum': 54, + \ 'col': 0, + \ 'type': 'E', + \ 'text': 'Items with a description must have content in it.', + \ }, + \ { + \ 'lnum': 24, + \ 'col': 0, + \ 'type': 'W', + \ 'text': 'Operations must have a non-empty `operationId`.', + \ }, + \ { + \ 'lnum': 40, + \ 'col': 0, + \ 'type': 'W', + \ 'text': 'operationIds must follow case convention: lower_snake_case', + \ }, + \ ], + \ ale_linters#openapi#ibm_validator#Handle(bufnr(''), [ + \ '', + \ '[Warning] No .validaterc file found. The validator will run in default mode.', + \ 'To configure the validator, create a .validaterc file.', + \ '', + \ 'errors', + \ '', + \ ' Message : Items with a description must have content in it.', + \ ' Path : paths./settings.patch.description', + \ ' Line : 54', + \ '', + \ 'warnings', + \ '', + \ ' Message : Operations must have a non-empty `operationId`.', + \ ' Path : paths./stats.get.operationId', + \ ' Line : 24', + \ '', + \ ' Message : operationIds must follow case convention: lower_snake_case', + \ ' Path : paths./settings.get.operationId', + \ ' Line : 40' + \ ]) diff --git a/test/handler/test_inko_handler.vader b/test/handler/test_inko_handler.vader new file mode 100644 index 00000000..6621d2d6 --- /dev/null +++ b/test/handler/test_inko_handler.vader @@ -0,0 +1,54 @@ +Before: + runtime ale_linters/inko/inko.vim + +After: + call ale#linter#Reset() + +Execute(The inko handler should parse errors correctly): + AssertEqual + \ [ + \ { + \ 'filename': ale#path#Simplify('/tmp/foo.inko'), + \ 'lnum': 4, + \ 'col': 5, + \ 'text': 'this is an error', + \ 'type': 'E', + \ } + \ ], + \ ale#handlers#inko#Handle(bufnr(''), [ + \ '[', + \ ' {', + \ ' "file": "/tmp/foo.inko",', + \ ' "line": 4,', + \ ' "column": 5,', + \ ' "message": "this is an error",', + \ ' "level": "error"', + \ ' }', + \ ']' + \ ]) + +Execute(The inko handler should parse warnings correctly): + AssertEqual + \ [ + \ { + \ 'filename': ale#path#Simplify('/tmp/foo.inko'), + \ 'lnum': 4, + \ 'col': 5, + \ 'text': 'this is a warning', + \ 'type': 'W', + \ } + \ ], + \ ale#handlers#inko#Handle(bufnr(''), [ + \ '[', + \ ' {', + \ ' "file": "/tmp/foo.inko",', + \ ' "line": 4,', + \ ' "column": 5,', + \ ' "message": "this is a warning",', + \ ' "level": "warning"', + \ ' }', + \ ']' + \ ]) + +Execute(The inko handler should handle empty output): + AssertEqual [], ale#handlers#inko#Handle(bufnr(''), []) diff --git a/test/handler/test_nix_handler.vader b/test/handler/test_nix_handler.vader index 398e1ac8..87e8b68f 100644 --- a/test/handler/test_nix_handler.vader +++ b/test/handler/test_nix_handler.vader @@ -8,6 +8,29 @@ Execute(The nix handler should parse nix-instantiate error messages correctly): AssertEqual \ [ \ { + \ 'lnum': 6, + \ 'col': 3, + \ 'type': 'E', + \ 'text': "syntax error, unexpected ']', expecting ';'", + \ }, + \ { + \ 'lnum': 3, + \ 'col': 5, + \ 'type': 'E', + \ 'text': "undefined variable 'foo'", + \ }, + \ + \ ], + \ ale_linters#nix#nix#Handle(bufnr(''), [ + \ "@nix {\"line\":6,\"column\":3,\"raw_msg\":\"syntax error, unexpected ']', expecting ';'\"}", + \ "@nix {\"line\":3,\"column\":5,\"raw_msg\":\"undefined variable 'foo'\"}", + \ "@nix {\"unrelated\":\"message\"}" + \ ]) + +Execute(The nix handler should parse message from old nix-instantiate correctly): + AssertEqual + \ [ + \ { \ 'lnum': 23, \ 'col': 14, \ 'text': 'error: syntax error, unexpected IN', diff --git a/test/handler/test_salt_salt_lint.vader b/test/handler/test_salt_salt_lint.vader new file mode 100644 index 00000000..7e234785 --- /dev/null +++ b/test/handler/test_salt_salt_lint.vader @@ -0,0 +1,34 @@ +Before: + runtime ale_linters/salt/salt_lint.vim + +After: + call ale#linter#Reset() + +Execute(The salt handler should parse lines correctly and show error in severity HIGH): + AssertEqual + \ [ + \ { + \ 'lnum': 5, + \ 'code': 207, + \ 'text': 'File modes should always be encapsulated in quotation marks', + \ 'type': 'E' + \ } + \ ], + \ ale_linters#salt#salt_lint#Handle(255, [ + \ '[{"id": "207", "message": "File modes should always be encapsulated in quotation marks", "filename": "test.sls", "linenumber": 5, "line": " - mode: 0755", "severity": "HIGH"}]' + \ ]) + + +Execute(The salt handler should parse lines correctly and show error in severity not HIGH): + AssertEqual + \ [ + \ { + \ 'lnum': 27, + \ 'code': 204, + \ 'text': 'Lines should be no longer that 160 chars', + \ 'type': 'W' + \ } + \ ], + \ ale_linters#salt#salt_lint#Handle(255, [ + \ '[{"id": "204", "message": "Lines should be no longer that 160 chars", "filename": "test2.sls", "linenumber": 27, "line": "this line is definitely longer than 160 chars, this line is definitely longer than 160 chars, this line is definitely longer than 160 chars", "severity": "VERY_LOW"}]' + \ ]) diff --git a/test/handler/test_spectral_handler.vader b/test/handler/test_spectral_handler.vader new file mode 100644 index 00000000..89a3ff1b --- /dev/null +++ b/test/handler/test_spectral_handler.vader @@ -0,0 +1,52 @@ +Before: + runtime ale_linters/yaml/spectral.vim + +After: + call ale#linter#Reset() + +Execute(spectral handler should parse lines correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 1, + \ 'col': 1, + \ 'code': 'oas3-api-servers', + \ 'text': 'OpenAPI `servers` must be present and non-empty array.', + \ 'type': 'W' + \ }, + \ { + \ 'lnum': 1, + \ 'col': 1, + \ 'code': 'oas3-schema', + \ 'text': 'Object should have required property `paths`.', + \ 'type': 'E' + \ }, + \ { + \ 'lnum': 1, + \ 'col': 1, + \ 'code': 'openapi-tags', + \ 'text': 'OpenAPI object should have non-empty `tags` array.', + \ 'type': 'W' + \ }, + \ { + \ 'lnum': 3, + \ 'col': 6, + \ 'code': 'info-contact', + \ 'text': 'Info object should contain `contact` object.', + \ 'type': 'W' + \ }, + \ { + \ 'lnum': 3, + \ 'col': 6, + \ 'code': 'oas3-schema', + \ 'text': '`info` property should have required property `version`.', + \ 'type': 'E' + \ }, + \ ], + \ ale#handlers#spectral#HandleSpectralOutput(bufnr(''), [ + \ 'openapi.yml:1:1 warning oas3-api-servers "OpenAPI `servers` must be present and non-empty array."', + \ 'openapi.yml:1:1 error oas3-schema "Object should have required property `paths`."', + \ 'openapi.yml:1:1 warning openapi-tags "OpenAPI object should have non-empty `tags` array."', + \ 'openapi.yml:3:6 warning info-contact "Info object should contain `contact` object."', + \ 'openapi.yml:3:6 error oas3-schema "`info` property should have required property `version`."', + \ ]) diff --git a/test/handler/test_swipl_handler.vader b/test/handler/test_swipl_handler.vader index 9e425cf6..81b8b9e5 100644 --- a/test/handler/test_swipl_handler.vader +++ b/test/handler/test_swipl_handler.vader @@ -35,6 +35,22 @@ Execute (The swipl handler should handle a warning / error of two lines): \ ' Singleton variables: [M]', \ ]) +Execute (The swipl handler should handle a warning / error of two lines in the new format): + call ale#test#SetFilename('test.pl') + AssertEqual + \ [ + \ { + \ 'lnum': 9, + \ 'col': 0, + \ 'text': 'Singleton variables: [M]', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#prolog#swipl#Handle(bufnr(''), [ + \ 'Warning: /path/to/test.pl:9:', + \ 'Warning: Singleton variables: [M]', + \ ]) + Execute (The swipl handler should join three or more lines with '. '): call ale#test#SetFilename('test.pl') AssertEqual @@ -79,6 +95,50 @@ Execute (The swipl handler should ignore warnings / errors 'No permission to cal \ ' vimscript: (multifile A)', \ ]) +Execute (The swipl handler should join three or more lines with '. ' on latest swipl): + call ale#test#SetFilename('test.pl') + AssertEqual + \ [ + \ { + \ 'lnum': 10, + \ 'col': 0, + \ 'text': 'Clauses of fib/2 are not together in the source-file. Earlier definition at /path/to/test.pl:7. Current predicate: f/0. Use :- discontiguous fib/2. to suppress this message', + \ 'type': 'W', + \ }, + \ ], + \ ale_linters#prolog#swipl#Handle(bufnr(''), [ + \ 'Warning: /path/to/test.pl:10:', + \ 'Warning: Clauses of fib/2 are not together in the source-file', + \ 'Warning: Earlier definition at /path/to/test.pl:7', + \ 'Warning: Current predicate: f/0', + \ 'Warning: Use :- discontiguous fib/2. to suppress this message', + \ ]) + +Execute (The swipl handler should ignore warnings / errors 'No permission to call sandboxed with latest swpl...'): + call ale#test#SetFilename('test.pl') + AssertEqual + \ [], + \ ale_linters#prolog#swipl#Handle(bufnr(''), [ + \ 'ERROR: /path/to/test.pl:11:', + \ 'ERROR: No permission to call sandboxed `''$set_predicate_attribute''(_G3416:_G3417,_G3413,_G3414)''', + \ 'ERROR: Reachable from:', + \ 'ERROR: system:''$set_pattr''(A,B,C,D)', + \ 'ERROR: system:''$set_pattr''(vimscript:A,B,C)', + \ 'ERROR: vimscript: (multifile A)', + \ 'ERROR: /path/to/test.pl:12:', + \ 'ERROR: No permission to call sandboxed `''$set_predicate_attribute''(_G205:_G206,_G202,_G203)''', + \ 'ERROR: Reachable from:', + \ 'ERROR: system:''$set_pattr''(A,B,C,D)', + \ 'ERROR: system:''$set_pattr''(vimscript:A,B,C)', + \ 'ERROR: vimscript: (multifile A)', + \ 'ERROR: /path/to/test.pl:13:', + \ 'ERROR: No permission to call sandboxed `''$set_predicate_attribute''(_G1808:_G1809,_G1805,_G1806)''', + \ 'ERROR: Reachable from:', + \ 'ERROR: system:''$set_pattr''(A,B,C,D)', + \ 'ERROR: system:''$set_pattr''(vimscript:A,B,C)', + \ 'ERROR: vimscript: (multifile A)', + \ ]) + Execute (The swipl handler should handle a warning / error with no line number): call ale#test#SetFilename('test.pl') AssertEqual diff --git a/test/handler/test_terraform_handler.vader b/test/handler/test_terraform_handler.vader index 976ce12a..64e2e578 100644 --- a/test/handler/test_terraform_handler.vader +++ b/test/handler/test_terraform_handler.vader @@ -1,34 +1,61 @@ Before: " Load the file which defines the linter. runtime ale_linters/terraform/terraform.vim + call ale#test#SetDirectory('/testplugin/test/terraform_files') + call ale#test#SetFilename('providers.tf') After: " Unload all linters again. call ale#linter#Reset() + call ale#test#RestoreDirectory() Execute(The output should be correct): AssertEqual \ [ \ { - \ 'lnum': 1, - \ 'col': 20, - \ 'type': 'E', - \ 'text': 'illegal char', + \ 'lnum': 17, + \ 'col': 13, + \ 'filename': ale#path#Simplify(g:dir . '/providers.tf'), + \ 'type': 'W', + \ 'text': 'Terraform 0.13 and earlier allowed provider version', \ }, \ { - \ 'lnum': 2, - \ 'col': 14, + \ 'lnum': 0, + \ 'col': 0, + \ 'filename': ale#path#Simplify(g:dir . '/providers.tf'), \ 'type': 'E', - \ 'text': 'literal not terminated', - \ }, - \ { - \ 'lnum': 1, - \ 'type': 'E', - \ 'text': 'object expected closing RBRACE got: EOF', - \ }, + \ 'text': 'Plugin reinitialization required. Please run "terraform"', + \ } \ ], \ ale_linters#terraform#terraform#Handle(bufnr(''), [ - \ 'Error running fmt: In <standard input>: At 1:20: illegal char', - \ 'Error running fmt: In <standard input>: At 2:14: literal not terminated', - \ 'Error running fmt: In <standard input>: object expected closing RBRACE got: EOF', + \ '{', + \ '"valid": false,', + \ '"error_count": 1,', + \ '"warning_count": 1,', + \ '"diagnostics": [', + \ ' {', + \ ' "severity": "warning",', + \ ' "summary": "Version constraints inside provider configuration blocks are deprecated",', + \ ' "detail": "Terraform 0.13 and earlier allowed provider version",', + \ ' "range": {', + \ ' "filename": "providers.tf",', + \ ' "start": {', + \ ' "line": 17,', + \ ' "column": 13,', + \ ' "byte": 669', + \ ' },', + \ ' "end": {', + \ ' "line": 17,', + \ ' "column": 24,', + \ ' "byte": 680', + \ ' }', + \ ' }', + \ ' },', + \ ' {', + \ ' "severity": "error",', + \ ' "summary": "Could not load plugin",', + \ ' "detail": "Plugin reinitialization required. Please run \"terraform\""', + \ ' }', + \ ' ]', + \ '}', \ ]) diff --git a/test/handler/test_vala_lint_handler.vader b/test/handler/test_vala_lint_handler.vader new file mode 100644 index 00000000..b8a4fbfa --- /dev/null +++ b/test/handler/test_vala_lint_handler.vader @@ -0,0 +1,54 @@ +Before: + runtime ale_linters/vala/vala_lint.vim + +After: + call ale#linter#Reset() + +Execute(The Vala-Lint handler should parse lines correctly): + AssertEqual + \ [ + \ { + \ 'lnum': 18, + \ 'col': 18, + \ 'text': 'Expected space before paren', + \ 'code': 'space-before-paren', + \ 'type': 'E', + \ }, + \ { + \ 'lnum': 64, + \ 'col': 37, + \ 'text': 'Expected space before paren', + \ 'code': 'space-before-paren', + \ 'type': 'W', + \ }, + \ { + \ 'lnum': 73, + \ 'col': 37, + \ 'text': 'Expected space before paren', + \ 'code': 'space-before-paren', + \ 'type': 'E', + \ }, + \ ], + \ ale_linters#vala#vala_lint#Handle(bufnr(''), [ + \ 'Application.vala', + \ ' 18.18 error Expected space before paren space-before-paren', + \ ' 64.37 warn Expected space before paren space-before-paren', + \ ' 73.37 error Expected space before paren space-before-paren', + \ ]) + +Execute(The Vala-Lint handler should ignore unknown error types): + AssertEqual + \ [ + \ { + \ 'lnum': 73, + \ 'col': 37, + \ 'text': 'Expected space before paren', + \ 'code': 'space-before-paren', + \ 'type': 'E', + \ }, + \ ], + \ ale_linters#vala#vala_lint#Handle(bufnr(''), [ + \ 'Application.vala', + \ ' 18.18 test Expected space before paren space-before-paren', + \ ' 73.37 error Expected space before paren space-before-paren', + \ ]) diff --git a/test/handler/test_yamllint_handler.vader b/test/handler/test_yamllint_handler.vader index 1aa0b9f5..dd51119c 100644 --- a/test/handler/test_yamllint_handler.vader +++ b/test/handler/test_yamllint_handler.vader @@ -3,7 +3,7 @@ Before: let g:ale_warn_about_trailing_whitespace = 1 - runtime! ale_linters/yaml/yamllint.vim + runtime! ale/handlers/yamllint.vim After: Restore @@ -29,7 +29,7 @@ Execute(Problems should be parsed correctly for yamllint): \ 'text': 'syntax error: expected the node content, but found ''<stream end>''', \ }, \ ], - \ ale_linters#yaml#yamllint#Handle(bufnr(''), [ + \ ale#handlers#yamllint#Handle(bufnr(''), [ \ 'something.yaml:1:1: [warning] missing document start "---" (document-start)', \ 'something.yml:2:1: [error] syntax error: expected the node content, but found ''<stream end>''', \ ]) @@ -45,7 +45,7 @@ Execute(The yamllint handler should respect ale_warn_about_trailing_whitespace): \ 'code': 'trailing-spaces', \ }, \ ], - \ ale_linters#yaml#yamllint#Handle(bufnr(''), [ + \ ale#handlers#yamllint#Handle(bufnr(''), [ \ 'something.yml:5:18: [error] trailing spaces (trailing-spaces)', \ ]) @@ -54,6 +54,6 @@ Execute(The yamllint handler should respect ale_warn_about_trailing_whitespace): AssertEqual \ [ \ ], - \ ale_linters#yaml#yamllint#Handle(bufnr(''), [ + \ ale#handlers#yamllint#Handle(bufnr(''), [ \ 'something.yml:5:18: [error] trailing spaces (trailing-spaces)', \ ]) diff --git a/test/nix/test.nix b/test/nix/test.nix new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/nix/test.nix diff --git a/test/nix/test_rnix_lsp.vader b/test/nix/test_rnix_lsp.vader new file mode 100644 index 00000000..bf62616b --- /dev/null +++ b/test/nix/test_rnix_lsp.vader @@ -0,0 +1,14 @@ +" Author: jD91mZM2 <me@krake.one> +" Description: Tests for rnix-lsp language client + +Before: + call ale#assert#SetUpLinterTest('nix', 'rnix_lsp') + +After: + call ale#assert#TearDownLinterTest() + +Execute(should start rnix-lsp): + call ale#test#SetFilename('./test.nix') + AssertLSPLanguage 'nix' + AssertLSPOptions {} + AssertLSPProject ale#path#Simplify('.') diff --git a/test/script/check-duplicate-tags b/test/script/check-duplicate-tags new file mode 100755 index 00000000..ec1de788 --- /dev/null +++ b/test/script/check-duplicate-tags @@ -0,0 +1,5 @@ +#!/usr/bin/env bash + +set -e + +grep --exclude=tags -roh '\*.*\*$' doc | sort | uniq -d diff --git a/test/script/check-supported-tools-tables b/test/script/check-supported-tools-tables index f4305707..d238e77f 100755 --- a/test/script/check-supported-tools-tables +++ b/test/script/check-supported-tools-tables @@ -15,14 +15,13 @@ while read -r; do if [[ "$REPLY" =~ ^! ]]; then language="${REPLY/!/}" else - # shellcheck disable=SC2001 echo "$language - $REPLY" fi done < <( grep '^\*\|^ *\*' doc/ale-supported-languages-and-tools.txt \ | sed -e '1,2d' \ | sed 's/^\* */!/' \ - | sed 's/^ *\* *\|!!\|\^\|(.*)\|`//g' \ + | sed -E 's/^ *\* *|!!|\^|\(.*\)|`//g' \ | sed 's/ *$//' ) > "$doc_file" @@ -30,13 +29,12 @@ while read -r; do if [[ "$REPLY" =~ ^! ]]; then language="${REPLY/!/}" else - # shellcheck disable=SC2001 echo "$language - $REPLY" fi done < <( grep '^\*\|^ *\*' supported-tools.md \ | sed 's/^\* */!/' \ - | sed 's/^ *\* *\|:floppy_disk:\|:warning:\|(.*)\|\[\|\].*\|-n flag//g' \ + | sed -E 's/^ *\* *|:floppy_disk:|:warning:|\(.*\)|\[|\].*|-n flag//g' \ | sed 's/ *$//' ) > "$readme_file" diff --git a/test/script/check-tag-alignment b/test/script/check-tag-alignment new file mode 100755 index 00000000..d41db160 --- /dev/null +++ b/test/script/check-tag-alignment @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +exit_code=0 + +# Documentation tags need to be aligned to the right margin, so look for +# tags which aren't at the right margin. +grep ' \*[^*]\+\*$' doc/ -r \ + | awk '{ sep = index($0, ":"); if (length(substr($0, sep + 1 )) < 79) { print } }' \ + | grep . && exit_code=1 + +exit $exit_code diff --git a/test/script/check-tag-references b/test/script/check-tag-references new file mode 100755 index 00000000..45e741fb --- /dev/null +++ b/test/script/check-tag-references @@ -0,0 +1,22 @@ +#!/usr/bin/env bash + +set -e + +exit_code=0 +tag_regex='[gb]\?:\?\(ale\|ALE\)[a-zA-Z_\-]\+' + +tags="$(mktemp -t tags.XXXXXXXX)" +refs="$(mktemp -t refs.XXXXXXXX)" +# Grep for tags and references, and complain if we find a reference without +# a tag for the reference. Only our tags will be included. +grep --exclude=tags -roh "\\*$tag_regex\\*" doc | sed 's/*//g' | sort -u > "$tags" +grep --exclude=tags -roh "|$tag_regex|" doc | sed 's/|//g' | sort -u > "$refs" + +exit_code=0 + +if ! [[ $(comm -23 $refs $tags | wc -l) -eq 0 ]]; then + exit_code=1 +fi + +rm "$tags" +rm "$refs" diff --git a/test/script/check-toc b/test/script/check-toc index 87a61262..f3f8a9ea 100755 --- a/test/script/check-toc +++ b/test/script/check-toc @@ -35,7 +35,7 @@ sed -n "$toc_start_line,$toc_end_line"p doc/ale.txt \ > "$toc_file" # Get all of the doc files in a natural sorted order. -doc_files="$(/usr/bin/env ls -1v doc | grep ^ale- | sed 's/^/doc\//' | paste -sd ' ' -)" +doc_files="$(/usr/bin/env ls -1v doc | grep '^ale-' | sed 's/^/doc\//' | paste -sd ' ' -)" # shellcheck disable=SC2086 grep -h '\*ale-.*-options\|^[a-z].*\*ale-.*\*$' $doc_files \ diff --git a/test/script/custom-checks b/test/script/custom-checks index ca9069e4..83afb28c 100755 --- a/test/script/custom-checks +++ b/test/script/custom-checks @@ -13,7 +13,7 @@ echo 'Custom warnings/errors follow:' echo set -o pipefail -docker run -a stdout "${docker_flags[@]}" test/script/custom-linting-rules . || exit_code=$? +docker run "${docker_flags[@]}" test/script/custom-linting-rules . || exit_code=$? set +o pipefail echo @@ -23,7 +23,10 @@ echo '========================================' echo 'Duplicate tags follow:' echo -grep --exclude=tags -roh '\*.*\*$' doc | sort | uniq -d || exit_code=$? +set -o pipefail +docker run "${docker_flags[@]}" test/script/check-duplicate-tags . || exit_code=$? +set +o pipefail +echo echo '========================================' echo 'Checking for invalid tag references' @@ -31,14 +34,9 @@ echo '========================================' echo 'Invalid tag references tags follow:' echo -tag_regex='[gb]\?:\?\(ale\|ALE\)[a-zA-Z_\-]\+' - -# Grep for tags and references, and complain if we find a reference without -# a tag for the reference. Only our tags will be included. -diff -u \ - <(grep --exclude=tags -roh "\\*$tag_regex\\*" doc | sort -u | sed 's/*//g') \ - <(grep --exclude=tags -roh "|$tag_regex|" doc | sort -u | sed 's/|//g') \ - | grep '^+[^+]' && exit_code=1 +set -o pipefail +docker run "${docker_flags[@]}" test/script/check-tag-references || exit_code=$? +set +o pipefail echo '========================================' echo 'diff supported-tools.md and doc/ale-supported-languages-and-tools.txt tables' @@ -46,7 +44,9 @@ echo '========================================' echo 'Differences follow:' echo -test/script/check-supported-tools-tables || exit_code=$? +set -o pipefail +docker run "${docker_flags[@]}" test/script/check-supported-tools-tables || exit_code=$? +set +o pipefail echo '========================================' echo 'Look for badly aligned doc tags' @@ -54,18 +54,18 @@ echo '========================================' echo 'Badly aligned tags follow:' echo -# Documentation tags need to be aligned to the right margin, so look for -# tags which aren't at the right margin. -grep ' \*[^*]\+\*$' doc/ -r \ - | awk '{ sep = index($0, ":"); if (length(substr($0, sep + 1 )) < 79) { print } }' \ - | grep . && exit_code=1 +set -o pipefail +docker run "${docker_flags[@]}" test/script/check-tag-alignment || exit_code=$? +set +o pipefail echo '========================================' echo 'Look for table of contents issues' echo '========================================' echo -test/script/check-toc || exit_code=$? +set -o pipefail +docker run "${docker_flags[@]}" test/script/check-toc || exit_code=$? +set +o pipefail echo '========================================' echo 'Check Python code' diff --git a/test/script/custom-linting-rules b/test/script/custom-linting-rules index 981a9459..69ab3cc8 100755 --- a/test/script/custom-linting-rules +++ b/test/script/custom-linting-rules @@ -53,17 +53,29 @@ check_errors() { regex="$1" message="$2" include_arg='' + exclude_arg='' if [ $# -gt 2 ]; then include_arg="--include $3" fi + if [ $# -gt 3 ]; then + shift + shift + shift + + while (( "$#" )); do + exclude_arg="$exclude_arg --exclude $1" + shift + done + fi + for directory in "${directories[@]}"; do # shellcheck disable=SC2086 while read -r; do RETURN_CODE=1 echo "$REPLY $message" - done < <(grep -H -n "$regex" $include_arg "$directory"/**/*.vim \ + done < <(grep -H -n "$regex" $include_arg $exclude_arg "$directory"/**/*.vim \ | grep -v 'no-custom-checks' \ | grep -o '^[^:]\+:[0-9]\+' \ | sed 's:^\./::') @@ -92,7 +104,7 @@ if (( FIX_ERRORS )); then done fi -# The arguments are: regex, explanation, [filename_filter] +# The arguments are: regex, explanation, [filename_filter], [list, of, exclusions] check_errors \ '^function.*) *$' \ 'Function without abort keyword (See :help except-compat)' @@ -114,7 +126,10 @@ check_errors '==?' "Use 'is?' instead of '==?'. 0 ==? 'foobar' is true" check_errors '!=#' "Use 'isnot#' instead of '!=#'. 0 !=# 'foobar' is false" check_errors '!=?' "Use 'isnot?' instead of '!=?'. 0 !=? 'foobar' is false" check_errors '^ *:\?echo' "Stray echo line. Use \`execute echo\` if you want to echo something" -check_errors $'name.:.*\'[a-z_]*[^a-z_0-9][a-z_0-9]*\',$' 'Use snake_case names for linters' '*/ale_linters/*' +# Exclusions for grandfathered-in exceptions +exclusions="clojure/clj_kondo.vim elixir/elixir_ls.vim go/golangci_lint.vim swift/swiftformat.vim" +# shellcheck disable=SC2086 +check_errors $'name.:.*\'[a-z_]*[^a-z_0-9][a-z_0-9]*\',$' 'Use snake_case names for linters' '*/ale_linters/*' $exclusions # Checks for improving type checks. check_errors $'\\(==.\\?\\|is\\) type([\'"]\+)' "Use 'is v:t_string' instead" check_errors '\(==.\?\|is\) type([0-9]\+)' "Use 'is v:t_number' instead" @@ -128,8 +143,8 @@ check_errors '\(!=.\?\|isnot\) type({})' "Use 'isnot v:t_dict' instead" check_errors '\(!=.\?\|isnot\) type(function([^)]\+))' "Use 'isnot v:t_func' instead" # Run a Python script to find lines that require padding around them. For -# users without Python installed, we'll skip these checks. Travis CI will run -# the script. +# users without Python installed, we'll skip these checks. GitHub Actions will +# run the script. if command -v python > /dev/null; then if ! test/script/block-padding-checker "$directory"/**/*.vim; then RETURN_CODE=1 diff --git a/test/smoke_test.vader b/test/smoke_test.vader index 0b126cc6..58206049 100644 --- a/test/smoke_test.vader +++ b/test/smoke_test.vader @@ -64,9 +64,9 @@ Execute(Linters should run with the default options): \ 'valid': 1, \ }] - " Try the test a few times over in NeoVim 0.3 or Windows, + " Try the test a few times over in NeoVim 0.3 or Windows or Vim 8.2, " where tests fail randomly. - for g:i in range(has('nvim-0.3') || has('win32') ? 5 : 1) + for g:i in range(has('nvim-0.3') || has('win32') || has('patch-8.2.2401') ? 5 : 1) call ale#Queue(0, '') call ale#test#WaitForJobs(2000) @@ -165,9 +165,9 @@ Execute(Previous errors should be removed when linters change): \ 'valid': 1, \}] - " Try the test a few times over in NeoVim 0.3 or Windows, + " Try the test a few times over in NeoVim 0.3 or VIm 8.2 or Windows, " where tests fail randomly. - for g:i in range(has('nvim-0.3') || has('win32') ? 5 : 1) + for g:i in range(has('nvim-0.3') || has('win32') || has('patch-8.2.2401') ? 5 : 1) call ale#Queue(0, '') call ale#test#WaitForJobs(2000) diff --git a/test/test_c_flag_parsing.vader b/test/test_c_flag_parsing.vader index 99722b17..8b02f2b9 100644 --- a/test/test_c_flag_parsing.vader +++ b/test/test_c_flag_parsing.vader @@ -482,6 +482,7 @@ Execute(We should include several important flags): \ . ' -idirafter ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/incafter')) \ . ' -iframework ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/incframework')) \ . ' -include ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/foo bar')) + \ . ' -imacros ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/incmacros')) \ . ' -Dmacro="value"' \ . ' -DGoal=9' \ . ' -D macro2' @@ -511,6 +512,8 @@ Execute(We should include several important flags): \ 'incframework', \ '-include', \ '''foo bar''', + \ '-imacros', + \ 'incmacros', \ '-Dmacro="value"', \ '-DGoal=9', \ '-D', @@ -559,6 +562,7 @@ Execute(We should quote the flags we need to quote): \ . ' -idirafter ' . ale#Escape(ale#path#Simplify(g:dir. '/test_c_projects/makefile_project/incafter')) \ . ' -iframework ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/incframework')) \ . ' -include ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/foo bar')) + \ . ' -imacros ' . ale#Escape(ale#path#Simplify(g:dir . '/test_c_projects/makefile_project/incmacros')) \ . ' ' . ale#Escape('-Dmacro="value"') \ . ' -DGoal=9' \ . ' -D macro2' @@ -591,6 +595,8 @@ Execute(We should quote the flags we need to quote): \ 'incframework', \ '-include', \ '''foo bar''', + \ '-imacros', + \ 'incmacros', \ '-Dmacro="value"', \ '-DGoal=9', \ '-D', diff --git a/test/test_deno_executable_detection.vader b/test/test_deno_executable_detection.vader new file mode 100644 index 00000000..edd408b1 --- /dev/null +++ b/test/test_deno_executable_detection.vader @@ -0,0 +1,19 @@ +Before: + runtime autoload/ale/handlers/deno.vim + +After: + unlet! g:ale_deno_executable + + call ale#linter#Reset() + +Execute(Default executable should be detected correctly): + AssertEqual + \ 'deno', + \ ale#handlers#deno#GetExecutable(bufnr('')) + +Execute(User specified executable should override default): + let g:ale_deno_executable = '/path/to/deno-bin' + AssertEqual + \ '/path/to/deno-bin', + \ ale#handlers#deno#GetExecutable(bufnr('')) + diff --git a/test/test_filetype_linter_defaults.vader b/test/test_filetype_linter_defaults.vader index e9980536..d4e708ec 100644 --- a/test/test_filetype_linter_defaults.vader +++ b/test/test_filetype_linter_defaults.vader @@ -70,3 +70,10 @@ Execute(The defaults for the verilog filetype should be correct): Execute(Default aliases for React should be defined): AssertEqual ['javascript', 'jsx'], ale#linter#ResolveFiletype('javascriptreact') AssertEqual ['typescript', 'tsx'], ale#linter#ResolveFiletype('typescriptreact') + +Execute(The defaults for the apkbuild filetype should be correct): + AssertEqual ['apkbuild_lint', 'secfixes_check'], GetLinterNames('apkbuild') + + let g:ale_linters_explicit = 1 + + AssertEqual [], GetLinterNames('apkbuild') diff --git a/test/test_floating_preview.vader b/test/test_floating_preview.vader new file mode 100644 index 00000000..43415556 --- /dev/null +++ b/test/test_floating_preview.vader @@ -0,0 +1,92 @@ +Before: + let g:ale_floating_preview = 0 + let g:ale_hover_to_floating_preview = 0 + let g:ale_detail_to_floating_preview = 0 + + runtime autoload/ale/floating_preview.vim + + let g:floated_lines = [] + let g:floating_preview_show_called = 0 + + " Stub out so we can track the call + function! ale#floating_preview#Show(lines, ...) abort + let g:floating_preview_show_called = 1 + let g:floated_lines = a:lines + endfunction + + let g:ale_buffer_info = { + \ bufnr('%'): { + \ 'loclist': [ + \ { + \ 'lnum': 1, + \ 'col': 10, + \ 'bufnr': bufnr('%'), + \ 'vcol': 0, + \ 'linter_name': 'notalinter', + \ 'nr': -1, + \ 'type': 'E', + \ 'code': 'semi', + \ 'text': "Missing semicolon.\r", + \ 'detail': "Every statement should end with a semicolon\nsecond line", + \ }, + \ ], + \ } + \} + + call ale#linter#Reset() + call ale#linter#PreventLoading('javascript') + +After: + Restore + + let g:ale_floating_preview = 0 + let g:ale_hover_to_floating_preview = 0 + let g:ale_detail_to_floating_preview = 0 + + call cursor(1, 1) + + let g:ale_buffer_info = {} + + " Close the preview window if it's open. + if &filetype is# 'ale-preview' + noautocmd :q! + endif + + call ale#linter#Reset() + + +Given javascript(A file with warnings/errors): + var x = 3 + 12345678 + var x = 5*2 + parseInt("10"); + // comment + +Execute(Floating preview is used with ALEDetail when g:ale_floating_preview set): + let g:ale_floating_preview = 1 + + call cursor(1, 10) + + ALEDetail + + let expected = ["Every statement should end with a semicolon", "second line"] + + AssertEqual 1, g:floating_preview_show_called + AssertEqual expected, g:floated_lines + +Execute(Floating preview is used with ALEDetail when g:ale_detail_to_floating_preview set): + let g:ale_detail_to_floating_preview = 1 + + call cursor(1, 10) + + ALEDetail + + let expected = ["Every statement should end with a semicolon", "second line"] + + AssertEqual 1, g:floating_preview_show_called + AssertEqual expected, g:floated_lines + +Execute(Floating preview is not used with ALEDetail by default): + call cursor(1, 10) + + ALEDetail + + AssertEqual 0, g:floating_preview_show_called diff --git a/test/test_hover.vader b/test/test_hover.vader index ed756396..7a9c8d91 100644 --- a/test/test_hover.vader +++ b/test/test_hover.vader @@ -7,9 +7,25 @@ Before: let g:item_list = [] let g:show_message_arg_list = [] + let g:ale_floating_preview = 0 + let g:ale_hover_to_floating_preview = 0 + let g:ale_detail_to_floating_preview = 0 + runtime autoload/ale/linter.vim runtime autoload/ale/lsp.vim + runtime autoload/ale/lsp_linter.vim runtime autoload/ale/util.vim + runtime autoload/ale/floating_preview.vim + runtime autoload/ale/hover.vim + + let g:floated_lines = [] + let g:floating_preview_show_called = 0 + + " Stub out so we can track the call + function! ale#floating_preview#Show(lines, ...) abort + let g:floating_preview_show_called = 1 + let g:floated_lines = a:lines + endfunction function! ale#lsp_linter#StartLSP(buffer, linter, callback) abort let g:Callback = a:callback @@ -50,6 +66,7 @@ Before: \) endfunction + After: call ale#hover#SetMap({}) call ale#test#RestoreDirectory() @@ -65,6 +82,7 @@ After: runtime autoload/ale/lsp_linter.vim runtime autoload/ale/lsp.vim runtime autoload/ale/util.vim + runtime autoload/ale/floating_preview.vim Given python(Some Python file): foo @@ -168,6 +186,28 @@ Execute(LSP hover response with lists of strings and marked strings should be ha \], g:show_message_arg_list AssertEqual {}, ale#hover#GetMap() +Execute(LSP hover with ale_floating_preview should float): + let g:ale_floating_preview = 1 + + call HandleValidLSPResult({'contents': "the message\ncontinuing"}) + + AssertEqual 1, g:floating_preview_show_called + AssertEqual ["the message", "continuing"], g:floated_lines + +Execute(LSP hover ale_hover_to_floating_preview should float): + let g:ale_hover_to_floating_preview = 1 + + call HandleValidLSPResult({'contents': "the message\ncontinuing"}) + + AssertEqual 1, g:floating_preview_show_called + AssertEqual ["the message", "continuing"], g:floated_lines + + +Execute(LSP hover by default should not float): + call HandleValidLSPResult({'contents': "the message\ncontinuing"}) + + AssertEqual 0, g:floating_preview_show_called + Execute(tsserver responses for documentation requests should be handled): call ale#hover#SetMap({3: {'show_documentation': 1, 'buffer': bufnr('')}}) @@ -187,3 +227,46 @@ Execute(tsserver responses for documentation requests should be handled): " The preview window should show the text. AssertEqual ['foo is a very good method'], ale#test#GetPreviewWindowText() silent! pclose + +Execute(hover with show_documentation should be in the preview window, not floating): + let g:ale_hover_to_floating_preview = 1 + let g:ale_floating_preview = 1 + + call ale#hover#SetMap({3: {'show_documentation': 1, 'buffer': bufnr('')}}) + + call ale#hover#HandleTSServerResponse( + \ 1, + \ { + \ 'command': 'quickinfo', + \ 'request_seq': 3, + \ 'success': v:true, + \ 'body': { + \ 'documentation': 'foo is a very good method', + \ 'displayString': 'foo bar ', + \ }, + \ } + \) + + let expected = ["Every statement should end with a semicolon", "second line"] + + AssertEqual 0, g:floating_preview_show_called + +Execute(TSServer hover without show_documentation and ale_floating_preview should float): + let g:ale_floating_preview = 1 + + call ale#hover#SetMap({3: {'buffer': bufnr('')}}) + + call ale#hover#HandleTSServerResponse( + \ 1, + \ { + \ 'command': 'quickinfo', + \ 'request_seq': 3, + \ 'success': v:true, + \ 'body': { + \ 'displayString': "the message\ncontinuing", + \ }, + \ } + \) + + AssertEqual 1, g:floating_preview_show_called + AssertEqual ["the message", "continuing"], g:floated_lines diff --git a/test/test_linting_updates_loclist.vader b/test/test_linting_updates_loclist.vader index 8a162703..41c86522 100644 --- a/test/test_linting_updates_loclist.vader +++ b/test/test_linting_updates_loclist.vader @@ -7,10 +7,12 @@ Before: Save g:ale_run_synchronously Save g:ale_set_lists_synchronously Save g:ale_buffer_info + Save g:ale_sign_offset " We want to check that sign IDs are set for this test. let g:ale_set_signs = 1 let g:ale_set_loclist = 1 + let g:ale_sign_offset = 2000000 " Disable features we don't need for these tests. let g:ale_set_quickfix = 0 let g:ale_set_highlights = 0 @@ -77,7 +79,7 @@ Execute(The loclist should be updated after linting is done): \ 'type': 'W', \ 'col': 10, \ 'text': 'Infix operators must be spaced. [Warning/space-infix-ops]', - \ 'sign_id': 1000001, + \ 'sign_id': 2000001, \ }, \ { \ 'lnum': 2, @@ -88,7 +90,7 @@ Execute(The loclist should be updated after linting is done): \ 'type': 'E', \ 'col': 10, \ 'text': 'Missing semicolon. [Error/semi]', - \ 'sign_id': 1000002, + \ 'sign_id': 2000002, \ } \ ], \ get(get(g:ale_buffer_info, bufnr('%'), {}), 'loclist', []) diff --git a/test/test_redundant_tsserver_rendering_avoided.vader b/test/test_redundant_tsserver_rendering_avoided.vader index 6125ebc2..bde5d152 100644 --- a/test/test_redundant_tsserver_rendering_avoided.vader +++ b/test/test_redundant_tsserver_rendering_avoided.vader @@ -111,7 +111,7 @@ Execute(An initial list of semantic errors should be handled): Assert g:ale_handle_loclist_called -Execute(Subsequent empty lists should be ignored): +Execute(Subsequent empty lists should be ignored - semantic): let g:ale_buffer_info[bufnr('')].semantic_loclist = [] call ale#lsp_linter#HandleLSPResponse(1, CreateError('semanticDiag', '')) @@ -138,3 +138,31 @@ Execute(Non-empty then non-empty semantic errors should be handled): call ale#lsp_linter#HandleLSPResponse(1, CreateError('semanticDiag', 'x')) Assert g:ale_handle_loclist_called + +Execute(Subsequent empty lists should be ignored - suggestion): + let g:ale_buffer_info[bufnr('')].suggestion_loclist = [] + + call ale#lsp_linter#HandleLSPResponse(1, CreateError('suggestionDiag', '')) + + Assert !g:ale_handle_loclist_called + +Execute(Empty then non-empty suggestion messages should be handled): + let g:ale_buffer_info[bufnr('')].suggestion_loclist = [] + + call ale#lsp_linter#HandleLSPResponse(1, CreateError('suggestionDiag', 'x')) + + Assert g:ale_handle_loclist_called + +Execute(Non-empty then empt suggestion messages should be handled): + let g:ale_buffer_info[bufnr('')].suggestion_loclist = CreateLoclist('x') + + call ale#lsp_linter#HandleLSPResponse(1, CreateError('suggestionDiag', '')) + + Assert g:ale_handle_loclist_called + +Execute(Non-empty then non-empty suggestion messages should be handled): + let g:ale_buffer_info[bufnr('')].suggestion_loclist = CreateLoclist('x') + + call ale#lsp_linter#HandleLSPResponse(1, CreateError('suggestionDiag', 'x')) + + Assert g:ale_handle_loclist_called diff --git a/test/test_socket_connections.vader b/test/test_socket_connections.vader index 6837fe51..9ea5580d 100644 --- a/test/test_socket_connections.vader +++ b/test/test_socket_connections.vader @@ -28,11 +28,17 @@ Before: endfunction let g:port = 10347 - let g:pid = str2nr(system( + let g:pid_tcp = str2nr(system( \ 'python' \ . ' ' . ale#Escape(g:dir . '/dumb_tcp_server.py') \ . ' ' . g:port \)) + let g:pipe_path = 'tmp_named_pipe' + let g:pid_pipe = str2nr(system( + \ 'python' + \ . ' ' . ale#Escape(g:dir . '/dumb_named_pipe_server.py') + \ . ' ' . g:pipe_path + \)) endif After: @@ -46,17 +52,23 @@ After: delfunction WaitForData delfunction TestCallback - if has_key(g:, 'pid') - call system('kill ' . g:pid) + if has_key(g:, 'pid_tcp') + call system('kill ' . g:pid_tcp) endif - unlet! g:pid + if has_key(g:, 'pid_pipe') + call system('kill ' . g:pid_pipe) + endif + + unlet! g:pid_tcp unlet! g:port + unlet! g:pid_pipe + unlet! g:pipe_path endif unlet! g:can_run_socket_tests -Execute(Sending and receiving connections to sockets should work): +Execute(Sending and receiving connections to tcp sockets should work): if g:can_run_socket_tests let g:channel_id = ale#socket#Open( \ '127.0.0.1:' . g:port, @@ -90,3 +102,38 @@ Execute(Sending and receiving connections to sockets should work): \ {'callback': function('function')} \) endif + +Execute(Sending and receiving connections to named pipe sockets should work): + if g:can_run_socket_tests && has('nvim') + let g:channel_id = ale#socket#Open( + \ g:pipe_path, + \ {'callback': function('TestCallback')} + \) + + Assert g:channel_id >= 0, 'The socket was not opened!' + + call ale#socket#Send(g:channel_id, 'hello') + call ale#socket#Send(g:channel_id, ' world') + + AssertEqual 1, ale#socket#IsOpen(g:channel_id) + + " Wait up to 1 second for the expected data to arrive. + call WaitForData('hello world', 1000) + + AssertEqual g:channel_id, g:channel_id_received + AssertEqual 'hello world', g:data_received + AssertEqual g:pipe_path, ale#socket#GetAddress(g:channel_id) + + call ale#socket#Close(g:channel_id) + + AssertEqual 0, ale#socket#IsOpen(g:channel_id) + AssertEqual '', ale#socket#GetAddress(g:channel_id) + endif + + " NeoVim versions which can't connect to sockets should just fail. + if has('nvim') && !exists('*chanclose') + AssertEqual -1, ale#socket#Open( + \ 'tmp_named_pipe', + \ {'callback': function('function')} + \) + endif diff --git a/test/typescript/test.ts b/test/typescript/test.ts new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/typescript/test.ts diff --git a/test/typescript/tsconfig.json b/test/typescript/tsconfig.json new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/typescript/tsconfig.json diff --git a/test/xo-test-files/monorepo/node_modules/xo/cli.js b/test/xo-test-files/monorepo/node_modules/xo/cli.js new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/xo-test-files/monorepo/node_modules/xo/cli.js diff --git a/test/xo-test-files/monorepo/package.json b/test/xo-test-files/monorepo/package.json new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/xo-test-files/monorepo/package.json diff --git a/test/xo-test-files/monorepo/packages/a/index.js b/test/xo-test-files/monorepo/packages/a/index.js new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/xo-test-files/monorepo/packages/a/index.js diff --git a/test/xo-test-files/monorepo/packages/a/index.ts b/test/xo-test-files/monorepo/packages/a/index.ts new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/xo-test-files/monorepo/packages/a/index.ts diff --git a/test/xo-test-files/monorepo/packages/a/package.json b/test/xo-test-files/monorepo/packages/a/package.json new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/test/xo-test-files/monorepo/packages/a/package.json |