From: martin f. krafft Date: Tue, 8 Apr 2025 15:04:25 +0000 (+0200) Subject: Merge commit '294584081929424aec883f90c7d6515b3743358d' as '.vim/bundle/vim-lsp-ale' X-Git-Url: https://git.madduck.net/etc/vim.git/commitdiff_plain/5179925d63a908e267c6675e2a2e64bf30d3f727?hp=-c Merge commit '294584081929424aec883f90c7d6515b3743358d' as '.vim/bundle/vim-lsp-ale' --- 5179925d63a908e267c6675e2a2e64bf30d3f727 diff --combined .vim/bundle/vim-lsp-ale/.codecov.yml index 00000000,53b2086e..53b2086e mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/.codecov.yml +++ b/.vim/bundle/vim-lsp-ale/.codecov.yml @@@ -1,0 -1,8 +1,8 @@@ + coverage: + status: + project: + default: + target: 0% + patch: + default: + target: 0% diff --combined .vim/bundle/vim-lsp-ale/.coveragerc index 00000000,8cddf91c..8cddf91c mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/.coveragerc +++ b/.vim/bundle/vim-lsp-ale/.coveragerc @@@ -1,0 -1,3 +1,3 @@@ + [run] + plugins = covimerage + data_file = .coverage_covimerage diff --combined .vim/bundle/vim-lsp-ale/.github/workflows/ci.yml index 00000000,2e4e3a46..2e4e3a46 mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/.github/workflows/ci.yml +++ b/.vim/bundle/vim-lsp-ale/.github/workflows/ci.yml @@@ -1,0 -1,101 +1,101 @@@ + name: CI + on: [push, pull_request] + + jobs: + vint: + name: Run vint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + - run: pip install vim-vint + - run: vint --warning --verbose --enable-neovim ./autoload ./plugin + + unit-test: + name: Unit tests + strategy: + matrix: + os: [macos-latest, ubuntu-latest, windows-latest] + neovim: [true, false] + fail-fast: false + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - name: Checkout themis.vim + uses: actions/checkout@v2 + with: + repository: thinca/vim-themis + path: vim-themis + - uses: rhysd/action-setup-vim@v1 + id: vim + with: + neovim: ${{ matrix.neovim }} + - name: Run unit tests + env: + THEMIS_VIM: ${{ steps.vim.outputs.executable }} + THEMIS_PROFILE: profile.txt + run: ./vim-themis/bin/themis ./test/unit + - uses: actions/setup-python@v2 + if: matrix.os != 'windows-latest' + - name: Report coverage + if: matrix.os != 'windows-latest' + run: | + # https://github.com/Vimjas/covimerage/issues/95 + pip install 'click<8.0.0' + pip install covimerage + covimerage write_coverage profile.txt + coverage report + coverage xml + - name: Upload coverage to codecov + if: matrix.os != 'windows-latest' + uses: codecov/codecov-action@v1 + with: + file: ./coverage.xml + + integ-test: + name: Integration tests + strategy: + matrix: + neovim: [true, false] + fail-fast: false + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Checkout themis.vim + uses: actions/checkout@v2 + with: + repository: thinca/vim-themis + path: vim-themis + - uses: rhysd/action-setup-vim@v1 + id: vim + with: + neovim: ${{ matrix.neovim }} + - name: Checkout vim-lsp + uses: actions/checkout@v2 + with: + repository: prabirshrestha/vim-lsp + path: test/integ/deps/vim-lsp + - name: Checkout ale + uses: actions/checkout@v2 + with: + repository: dense-analysis/ale + path: test/integ/deps/ale + - name: Install rust-analyzer + run: | + mkdir ~/bin + curl --fail -L https://github.com/rust-analyzer/rust-analyzer/releases/latest/download/rust-analyzer-x86_64-unknown-linux-gnu.gz -o rust-analyzer.gz + gunzip ./rust-analyzer.gz + chmod +x ./rust-analyzer + mv ./rust-analyzer ~/bin + echo "$HOME/bin" >> $GITHUB_PATH + - name: Run integration tests + env: + THEMIS_VIM: ${{ steps.vim.outputs.executable }} + run: ./vim-themis/bin/themis ./test/integ + - name: Show runtime information + if: ${{ failure() }} + run: | + echo 'integ_messages.txt' + [ -f test/integ/integ_messages.txt ] && cat test/integ/integ_messages.txt + echo 'lsp-log.txt' + [ -f test/integ/lsp-log.txt ] && cat test/integ/lsp-log.txt diff --combined .vim/bundle/vim-lsp-ale/.gitignore index 00000000,0a56e3fc..0a56e3fc mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/.gitignore +++ b/.vim/bundle/vim-lsp-ale/.gitignore @@@ -1,0 -1,1 +1,1 @@@ + /doc/tags diff --combined .vim/bundle/vim-lsp-ale/LICENSE index 00000000,b0687ade..b0687ade mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/LICENSE +++ b/.vim/bundle/vim-lsp-ale/LICENSE @@@ -1,0 -1,20 +1,20 @@@ + The MIT License (MIT) + + Copyright (c) 2021 rhysd + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --combined .vim/bundle/vim-lsp-ale/README.md index 00000000,2734b07c..2734b07c mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/README.md +++ b/.vim/bundle/vim-lsp-ale/README.md @@@ -1,0 -1,75 +1,75 @@@ + [vim-lsp][] + [ALE][] + ===================== + [![Build Status][ci-badge]][ci] + [![Coverage Status][codecov-badge]][codecov] + + [vim-lsp-ale][] is a Vim plugin for bridge between [vim-lsp][] and [ALE][]. Diagnostics results received + by vim-lsp are shown in ALE's interface. + + When simply using ALE and vim-lsp, both plugins run LSP servers respectively. Running multiple server processes + consume resources and may cause some issues. And showing lint results from multiple plugins is confusing. + vim-lsp-ale solves the problem. + + screencast + + ## Installation + + Install [vim-lsp][], [ale][ALE], [vim-lsp-ale][] with your favorite package manager or `:packadd` in your `.vimrc`. + + An example with [vim-plug](https://github.com/junegunn/vim-plug): + + ```viml + Plug 'dense-analysis/ale' + Plug 'prabirshrestha/vim-lsp' + Plug 'rhysd/vim-lsp-ale' + ``` + + ## Usage + + Register LSP servers you want to use with `lsp#register_server` and set `vim-lsp` linter to `g:ale_linters` + for filetypes you want to check with vim-lsp. + + The following example configures `gopls` to check Go sources. + + ```vim + " LSP configurations for vim-lsp + if executable('gopls') + autocmd User lsp_setup call lsp#register_server({ + \ 'name': 'gopls', + \ 'cmd': ['gopls'], + \ 'allowlist': ['go', 'gomod'], + \ }) + endif + + " Set 'vim-lsp' linter + let g:ale_linters = { + \ 'go': ['golint'], " vim-lsp is implicitly active + \ } + ``` + + This plugin configures vim-lsp and ALE automatically. You don't need to setup various variables. + + When opening a source code including some lint errors, vim-lsp will receive the errors from language server + and ALE will report the errors in the buffer. + + ALE supports also many external programs. All errors can be seen in one place. The above example enables + vim-lsp and golint. + + For more details, see [the documentation](./doc/vim-lsp-ale.txt). + + ## Testing + + There are unit tests and integration tests. CI runs on GitHub Actions. + See [test/README.md](./test/README.md) for more details. + + ## License + + Licensed under [the MIT license](./LICENSE). + + [vim-lsp]: https://github.com/prabirshrestha/vim-lsp + [ALE]: https://github.com/dense-analysis/ale + [vim-lsp-ale]: https://github.com/rhysd/vim-lsp-ale + [ci-badge]: https://github.com/rhysd/vim-lsp-ale/workflows/CI/badge.svg?branch=master&event=push + [ci]: https://github.com/rhysd/vim-lsp-ale/actions?query=workflow%3ACI+branch%3Amaster + [codecov-badge]: https://codecov.io/gh/rhysd/vim-lsp-ale/branch/master/graph/badge.svg + [codecov]: https://codecov.io/gh/rhysd/vim-lsp-ale diff --combined .vim/bundle/vim-lsp-ale/autoload/lsp/ale.vim index 00000000,04db1355..04db1355 mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/autoload/lsp/ale.vim +++ b/.vim/bundle/vim-lsp-ale/autoload/lsp/ale.vim @@@ -1,0 -1,203 +1,203 @@@ + " DiagnosticSeverity + let s:ERROR = 1 + let s:WARN = 2 + let s:INFO = 3 + let s:HINT = 4 + + let s:Dispose = v:null + + function! s:severity_threshold() abort + let s = g:lsp_ale_diagnostics_severity + if s ==? 'error' + return s:ERROR + elseif s ==? 'warning' || s ==? 'warn' + return s:WARN + elseif s ==? 'information' || s ==? 'info' + return s:INFO + elseif s ==? 'hint' + return s:HINT + else + throw 'vim-lsp-ale: Unexpected severity "' . s . '". Severity must be one of "error", "warning", "information", "hint"' + endif + endfunction + + function! s:get_loc_type(severity) abort + if a:severity == s:ERROR + return 'E' + elseif a:severity == s:WARN + return 'W' + elseif a:severity == s:INFO + return 'I' + elseif a:severity == s:HINT + return 'H' + else + throw 'vim-lsp-ale: Unexpected severity: ' . a:severity + endif + endfunction + + let s:prev_num_diags = {} + function! lsp#ale#_reset_prev_num_diags() abort + let s:prev_num_diags = {} + endfunction + + function! s:can_skip_diags(server, uri, diags) abort + if !has_key(s:prev_num_diags, a:server) + let s:prev_num_diags[a:server] = {} + endif + let prev = s:prev_num_diags[a:server] + + let num_diags = len(a:diags) + if num_diags == 0 && get(prev, a:uri, -1) == 0 + " Some language servers send diagnostics notifications even if the + " results are not changed from previous. It's hard to check the + " notifications are perfectly the same as previous. Here only checks + " emptiness and skip if both previous ones and current ones are + " empty. + " I believe programmers usually try to keep no lint errors in the + " source code they are writing :) + return v:true + endif + + let prev[a:uri] = num_diags + return v:false + endfunction + + function! s:can_skip_all_diags(uri, all_diags) abort + for [server, diags] in items(a:all_diags) + if !s:can_skip_diags(server, a:uri, diags.params.diagnostics) + return v:false + endif + endfor + return v:true + endfunction + + function! s:is_active_linter() abort + if g:lsp_ale_auto_enable_linter + return v:true + endif + let active_linters = get(b:, 'ale_linters', get(g:ale_linters, &filetype, [])) + return index(active_linters, 'vim-lsp') >= 0 + endf + + function! lsp#ale#on_ale_want_results(bufnr) abort + " Note: Checking lsp#internal#diagnostics#state#_is_enabled_for_buffer here. If previous lint + " errors remain in a buffer, they won't be updated when vim-lsp is disabled for the buffer. + if s:Dispose is v:null || !lsp#internal#diagnostics#state#_is_enabled_for_buffer(a:bufnr) + return + endif + + let uri = lsp#utils#get_buffer_uri(a:bufnr) + let all_diags = lsp#internal#diagnostics#state#_get_all_diagnostics_grouped_by_server_for_uri(uri) + if empty(all_diags) || s:can_skip_all_diags(uri, all_diags) + " Do nothing when no diagnostics results + return + endif + + if s:is_active_linter() + call ale#other_source#StartChecking(a:bufnr, 'vim-lsp') + " Avoid the issue that sign and highlight are not set + " https://github.com/dense-analysis/ale/issues/3690 + call timer_start(0, {-> s:notify_diag_to_ale(a:bufnr, all_diags) }) + endif + endfunction + + function! s:notify_diag_to_ale(bufnr, diags) abort + try + let threshold = s:severity_threshold() + let results = [] + for [server, diag] in items(a:diags) + " Note: Do not filter `diag` destructively since the object is also used by vim-lsp + let locs = lsp#ui#vim#utils#diagnostics_to_loc_list({'response': diag}) + let idx = 0 + for loc in locs + let severity = get(diag.params.diagnostics[idx], 'severity', s:ERROR) + if severity > threshold + continue + endif + let loc.text = '[' . server . '] ' . loc.text + let loc.type = s:get_loc_type(severity) + let results += [loc] + let idx += 1 + endfor + endfor + catch + " Since ale#other_source#StartChecking() was already called, ale#other_source#ShowResults() + " needs to be called to notify ALE that checking was done. + call ale#other_source#ShowResults(a:bufnr, 'vim-lsp', []) + let msg = v:exception . ' at ' . v:throwpoint + if msg !~# '^vim-lsp-ale: ' + " Avoid E608 on rethrowing exceptions from Vim script runtime + let msg = 'vim-lsp-ale: Error while notifying results to ALE: ' . msg + endif + throw msg + endtry + call ale#other_source#ShowResults(a:bufnr, 'vim-lsp', results) + endfunction + + function! s:notify_diag_to_ale_for_buf(bufnr) abort + if !s:is_active_linter() + return + endif + + let uri = lsp#utils#get_buffer_uri(a:bufnr) + let diags = lsp#internal#diagnostics#state#_get_all_diagnostics_grouped_by_server_for_uri(uri) + call s:notify_diag_to_ale(a:bufnr, diags) + endfunction + + function! s:on_diagnostics(res) abort + let uri = a:res.response.params.uri + if s:can_skip_diags(a:res.server, uri, a:res.response.params.diagnostics) + return + endif + + let path = lsp#utils#uri_to_path(uri) + let bufnr = bufnr('^' . path . '$') + if bufnr == -1 + " This branch is reachable when vim-lsp receives some notifications + " but the buffer for them was already deleted. This can happen since + " notifications are asynchronous + return + endif + + call ale#other_source#StartChecking(bufnr, 'vim-lsp') + " Use timer_start to ensure calling s:notify_diag_to_ale after all + " subscribers handled the publishDiagnostics event. + " lsp_setup is hooked before vim-lsp sets various internal hooks. So this + " function is called before the response is not handled by vim-lsp yet. + call timer_start(0, {-> s:notify_diag_to_ale_for_buf(bufnr) }) + endfunction + + function! s:is_diagnostics_response(item) abort + if !has_key(a:item, 'server') || !has_key(a:item, 'response') + return v:false + endif + let res = a:item.response + if !has_key(res, 'method') + return v:false + endif + return res.method ==# 'textDocument/publishDiagnostics' + endfunction + + function! lsp#ale#enable() abort + if s:Dispose isnot v:null + return + endif + + let s:Dispose = lsp#callbag#pipe( + \ lsp#stream(), + \ lsp#callbag#filter(funcref('s:is_diagnostics_response')), + \ lsp#callbag#subscribe({ 'next': funcref('s:on_diagnostics') }), + \ ) + endfunction + + function! lsp#ale#disable() abort + if s:Dispose is v:null + return + endif + call s:Dispose() + let s:Dispose = v:null + endfunction + + function! lsp#ale#enabled() abort + return s:Dispose isnot v:null + endfunction diff --combined .vim/bundle/vim-lsp-ale/doc/vim-lsp-ale.txt index 00000000,1e4e578c..1e4e578c mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/doc/vim-lsp-ale.txt +++ b/.vim/bundle/vim-lsp-ale/doc/vim-lsp-ale.txt @@@ -1,0 -1,213 +1,213 @@@ + *vim-lsp-ale.txt* Bridge between vim-lsp and ALE + + Author: rhysd + + CONTENTS *vim-lsp-ale-contents* + + Introduction |vim-lsp-ale-introduction| + Install |vim-lsp-ale-install| + Usage |vim-lsp-ale-usage| + Variables |vim-lsp-ale-variables| + Functions |vim-lsp-ale-functions| + Issues |vim-lsp-ale-issues| + License |vim-lsp-ale-license| + + + ============================================================================== + INTRODUCTION *vim-lsp-ale-introduction* + + *vim-lsp-ale* is a plugin for bridge between |vim-lsp| and |ale|. + + When using ALE and vim-lsp, both plugins run language server process + respectively. It's resource consuming and may cause some issues due to + multiple server processes running at the same time. + + |vim-lsp-ale| solves the problem by getting diagnostics results from vim-lsp + and by sending them to ALE. It means vim-lsp can be handled as one of linters + supported by ALE. + + It's also possible to disable LSP features in ALE and use both ALE and + vim-lsp's |:LspDocumentDiagnostics| together. But managing linter results + with multiple plugins is complicated and confusing since behaviors of each + plugins are not persistent. + + Screencast: https://github.com/rhysd/ss/blob/master/vim-lsp-ale/main.gif + + ============================================================================== + INSTALL *vim-lsp-ale-install* + + Install |ale|, |vim-lsp| and |vim-lsp-ale| with your favorite plugin manager + or using |:packadd|. + The following is an example using vim-plug. + + > + Plug 'dense-analysis/ale' + Plug 'prabirshrestha/vim-lsp' + Plug 'rhysd/vim-lsp-ale' + < + Repositories: + + - ALE: https://github.com/dense-analysis/ale/ + - vim-lsp: https://github.com/prabirshrestha/vim-lsp + - vim-lsp-ale: https://github.com/rhysd/vim-lsp-ale + + + ============================================================================== + USAGE *vim-lsp-ale-usage* + + Register LSP servers you want to use with |lsp#register_server()| and set + "vim-lsp" linter to |g:ale_linters| for filetypes you want to check with + vim-lsp. + + The following example configures gopls and golint to check Go sources. ALE + will automatically reports diagnostics results from gopls and lint errrors + from golint when you're writing Go source code. + > + if executable('gopls') + autocmd User lsp_setup call lsp#register_server({ + \ 'name': 'gopls', + \ 'cmd': ['gopls'], + \ 'allowlist': ['go', 'gomod'], + \ }) + endif + let g:ale_linters = { + \ 'go': ['vim-lsp', 'golint'], + \ } + < + gopls: https://github.com/golang/tools/tree/master/gopls + + vim-lsp-ale configures vim-lsp and ALE automatically. You don't need to setup + various variables for them. + + vim-lsp-ale automatically does: + + - disable showing diagnostics results from vim-lsp since ALE will show the + results + - disable LSP support of ALE since vim-lsp handles all LSP requests/responses + + If you don't want them to be done automatically, see + |g:lsp_ale_auto_config_vim_lsp| and |g:lsp_ale_auto_config_ale| + + + ============================================================================== + VARIABLES *vim-lsp-ale-variables* + + Behavior of vim-lsp-ale can be customized with some global variables. + + ------------------------------------------------------------------------------ + *g:lsp_ale_auto_config_vim_lsp* (Default: |v:true|) + + When |v:true| is set, vim-lsp-ale automatically sets several variables + for configuring vim-lsp not to show diagnostics results in vim-lsp side. + + At the time of writing, setting |v:true| is the same as: + > + let g:lsp_diagnostics_enabled = 1 + let g:lsp_diagnostics_echo_cursor = 0 + let g:lsp_diagnostics_float_cursor = 0 + let g:lsp_diagnostics_highlights_enabled = 0 + let g:lsp_diagnostics_signs_enabled = 0 + let g:lsp_diagnostics_virtual_text_enabled = 0 + < + When |v:false| is set, vim-lsp-ale does not set any variables to configure + vim-lsp so that you can configure them by yourself. + + ------------------------------------------------------------------------------ + *g:lsp_ale_auto_config_ale* (Default: |v:true|) + + When |v:true| is set, vim-lsp-ale automatically sets several variables + for configuring ALE not to start LSP server process. + + At the time of writing, setting |v:true| is the same as: + > + let g:ale_disable_lsp = 1 + < + When |v:false| is set, vim-lsp-ale does not set any variables to configure + ALE so that you can configure them by yourself. + + ------------------------------------------------------------------------------ + *g:lsp_ale_auto_enable_linter* (Default: |v:true|) + + When |v:true| is set, vim-lsp-ale automatically enables itself as a linter for + all filetypes. It does not modify |g:ale_linters|. + + When |v:false| is set, vim-lsp-ale is only active when configured as a linter + for a filetype: + > + let g:ale_linters = { + \ 'go': ['vim-lsp'], + \ 'lua': ['vim-lsp'], + \ 'python': ['vim-lsp'], + \ } + < + ------------------------------------------------------------------------------ + *g:lsp_ale_diagnostics_severity* (Default: "information") + + Severity level of reported diagnostics results. Possible values are "error", + "warning", "information", "hint". Diagnostics results will be filtered by the + severity set to this variable. + For example, when "warning" is set, "error"/"warning" results are shown + and "information"/"hint" results are not shown. + + + ============================================================================== + FUNCTIONS *vim-lsp-ale-functions* + + ------------------------------------------------------------------------------ + lsp#ale#enable() *lsp#ale#enable* + + Enables bridge between vim-lsp and ALE. This function is automatically called + when |lsp_setup| autocmd event is triggered by vim-lsp. So basically you don't + need to call this function. + + ------------------------------------------------------------------------------ + lsp#ale#disable() *lsp#ale#disable* + + Disables bridge between vim-lsp and ALE. After this function is called, + diagnostics results will no longer be sent to ALE until |lsp#ale#enable| is + called again. + + ------------------------------------------------------------------------------ + lsp#ale#enabled() *lsp#ale#enabled* + + Returns whether bridge between vim-lsp and ALE is enabled. + + + ============================================================================== + ISSUES *vim-lsp-ale-issues* + + When you find some issues or you have some feature requests to vim-lsp-ale, + visit GitHub repository page and make a new issue: + + https://github.com/rhysd/vim-lsp-ale/issues/new + + + ============================================================================== + LICENSE *vim-lsp-ale-license* + + vim-lsp-ale is distributed under the MIT license. + > + The MIT License (MIT) + + Copyright (c) 2021 rhysd + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do so, + subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR + THE USE OR OTHER DEALINGS IN THE SOFTWARE. + < + + ============================================================================== + vim:tw=78:ts=8:ft=help:norl:et:fen:fdl=0: diff --combined .vim/bundle/vim-lsp-ale/plugin/lsp_ale.vim index 00000000,74ea9296..74ea9296 mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/plugin/lsp_ale.vim +++ b/.vim/bundle/vim-lsp-ale/plugin/lsp_ale.vim @@@ -1,0 -1,28 +1,28 @@@ + if (exists('g:loaded_lsp_ale') && g:loaded_lsp_ale) || &cp + finish + endif + let g:loaded_lsp_ale = 1 + + let g:lsp_ale_diagnostics_severity = get(g:, 'lsp_ale_diagnostics_severity', 'information') + let g:lsp_ale_auto_enable_linter = get(g:, 'lsp_ale_auto_enable_linter', v:true) + + if get(g:, 'lsp_ale_auto_config_vim_lsp', v:true) + " Enable diagnostics and disable all functionalities to show error + " messages by vim-lsp + let g:lsp_diagnostics_enabled = 1 + let g:lsp_diagnostics_echo_cursor = 0 + let g:lsp_diagnostics_float_cursor = 0 + let g:lsp_diagnostics_highlights_enabled = 0 + let g:lsp_diagnostics_signs_enabled = 0 + let g:lsp_diagnostics_virtual_text_enabled = 0 + endif + if get(g:, 'lsp_ale_auto_config_ale', v:true) + " Disable ALE's LSP integration + let g:ale_disable_lsp = 1 + endif + + augroup plugin-lsp-ale + autocmd! + autocmd User lsp_setup call lsp#ale#enable() + autocmd User ALEWantResults call lsp#ale#on_ale_want_results(g:ale_want_results_buffer) + augroup END diff --combined .vim/bundle/vim-lsp-ale/test/README.md index 00000000,e566c2a4..e566c2a4 mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/README.md +++ b/.vim/bundle/vim-lsp-ale/test/README.md @@@ -1,0 -1,103 +1,103 @@@ + Tests + ===== + + ## Directory structure + + - [`test/unit`](./unit): Unit tests + - [`test/unit/test.vimspec`](./unit/test.vimspec): Unit test cases + - [`test/unit/runtime`](./unit/runtime): Runtime directory loaded on running unit tests. They mocks several external APIs like `ale#*` or `lsp#*` + - [`test/integ`](./integ): Integration tests + - [`test/integ/test.vimspec`](./integ/test.vimspec): Integration test cases + - [`test/integ/deps`](./integ/deps): Dependant plugins + + ## Unit tests + + Unit tests confirm vim-lsp-ale works as intended. + + ### Prerequisites + + Unit tests can be run with no dependency because they mock every external API. + + [vim-themis](https://github.com/thinca/vim-themis) is used as test runner. + + By default, it runs tests with `vim` command. When running tests with Neovim, set `THEMIS_VIM=nvim` environment variable. + + ### Run unit tests + + ```sh + cd path/to/vim-lsp-ale + git clone https://github.com/thinca/vim-themis.git + + # Run tests with Vim + ./vim-themis/bin/themis ./test/unit/ + + # Run tests with NeoVim + THEMIS_VIM=nvim ./vim-themis/bin/themis ./test/unit/ + ``` + + ### Measure unit test coverage + + [covimerage](https://github.com/Vimjas/covimerage) is used to measure test coverage. Install it by `pip install covimerage`. + + Set a file path to `THEMIS_PROFILE` environment variable and run unit tests. Vim will store the profile data to the file. + `covimerage` command will convert the profile data into coverage data for `coverage` command provided by Python. + + ```sh + cd path/to/vim-lsp-ale + git clone https://github.com/thinca/vim-themis.git + + # Run test case with $THEMIS_PROFILE environment variable + THEMIS_PROFILE=profile.txt ./vim-themis/bin/themis ./test/unit + + # Store coverage data at .coverage_covimerage converted from the profile data + covimerage write_coverage profile.txt + + # Show coverage report by `coverage` command + coverage report + ``` + + ## Integration tests + + Integration tests confirm integrity among vim-lsp, ALE, vim-lsp-ale and a language server. + + ### Prerequisites + + Integration tests require all dependencies are installed in [deps](./integ/deps) directory. + + ```sh + cd path/to/vim-lsp-ale + git clone https://github.com/prabirshrestha/vim-lsp.git test/integ/deps/vim-lsp + git clone https://github.com/dense-analysis/ale.git test/integ/deps/ale + ``` + + [rust-analyzer](https://rust-analyzer.github.io/) is used as language server to run integration tests. + Download the binary following [the instruction](https://rust-analyzer.github.io/manual.html#rust-analyzer-language-server-binary) + and put the binary in `$PATH` directory. + + And [vim-themis](https://github.com/thinca/vim-themis) is used as test runner. + + Note that integration tests were not confirmed on Windows. + + ### Run integration tests + + ```sh + cd path/to/vim-lsp-ale + git clone https://github.com/thinca/vim-themis.git + ./vim-themis/bin/themis ./test/integ/ + ``` + + ### Log files + + When some integration tests fail, the following log files would be useful to investigate the failure. + + - `test/integ/integ_messages.txt`: Messages in `:message` area while running the tests + - `test/integ/lsp-log.txt`: Log information of vim-lsp. It records communications between vim-lsp and a language server + + ## CI + + Tests are run continuously on GitHub Actions. + + https://github.com/rhysd/vim-lsp-ale/actions?query=workflow%3ACI + + - Unit tests are run on Linux, macOS and Windows with Vim and Neovim + - Integration tests are run on Linux with Vim and Neovim diff --combined .vim/bundle/vim-lsp-ale/test/integ/.gitignore index 00000000,d864a6f0..d864a6f0 mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/integ/.gitignore +++ b/.vim/bundle/vim-lsp-ale/test/integ/.gitignore @@@ -1,0 -1,4 +1,4 @@@ + /deps/vim-lsp + /deps/ale + /lsp-log.txt + /integ_messages.txt diff --combined .vim/bundle/vim-lsp-ale/test/integ/.themisrc index 00000000,fb5c9f0f..fb5c9f0f mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/integ/.themisrc +++ b/.vim/bundle/vim-lsp-ale/test/integ/.themisrc @@@ -1,0 -1,44 +1,44 @@@ + call themis#option('exclude', 'test/README.md') + + let s:dir = expand(':p:h') + let s:sep = has('win32') ? '\' : '/' + let s:vim_lsp_dir = join([s:dir, 'deps', 'vim-lsp'], s:sep) + let s:ale_dir = join([s:dir, 'deps', 'ale'], s:sep) + + if !isdirectory(s:vim_lsp_dir) + throw 'vim-lsp is not cloned at ' . s:vim_lsp_dir + endif + + if !isdirectory(s:ale_dir) + throw 'ALE is not cloned at ' . s:ale_dir + endif + + function! IntegTestRootDir() abort + return s:dir + endfunction + + execute 'set rtp+=' . s:vim_lsp_dir + execute 'set rtp+=' . s:ale_dir + filetype plugin indent on + + let g:lsp_log_file = 'lsp-log.txt' + autocmd User lsp_setup call lsp#register_server({ + \ 'name': 'rust-analyzer', + \ 'cmd': { server_info -> ['rust-analyzer'] }, + \ 'allowlist': ['rust'], + \ }) + + let g:ale_linters = { 'rust': ['vim-lsp'] } + + runtime plugin/lsp_ale.vim + runtime plugin/lsp.vim + runtime plugin/ale.vim + + " This is called automatically at VimEnter, but our tests load vim-lsp + " after the event. So manually call it here + call lsp#enable() + + let s:helper = themis#helper('assert') + call themis#helper('command').with(s:helper) + + " vim: set ft=vim: diff --combined .vim/bundle/vim-lsp-ale/test/integ/deps/.gitkeep index 00000000,00000000..e69de29b new file mode 100644 --- /dev/null +++ b/.vim/bundle/vim-lsp-ale/test/integ/deps/.gitkeep diff --combined .vim/bundle/vim-lsp-ale/test/integ/project/.gitignore index 00000000,53eaa219..53eaa219 mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/integ/project/.gitignore +++ b/.vim/bundle/vim-lsp-ale/test/integ/project/.gitignore @@@ -1,0 -1,2 +1,2 @@@ + /target + **/*.rs.bk diff --combined .vim/bundle/vim-lsp-ale/test/integ/project/Cargo.lock index 00000000,52257f66..52257f66 mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/integ/project/Cargo.lock +++ b/.vim/bundle/vim-lsp-ale/test/integ/project/Cargo.lock @@@ -1,0 -1,5 +1,5 @@@ + # This file is automatically @generated by Cargo. + # It is not intended for manual editing. + [[package]] + name = "project" + version = "0.1.0" diff --combined .vim/bundle/vim-lsp-ale/test/integ/project/Cargo.toml index 00000000,5217cb04..5217cb04 mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/integ/project/Cargo.toml +++ b/.vim/bundle/vim-lsp-ale/test/integ/project/Cargo.toml @@@ -1,0 -1,9 +1,9 @@@ + [package] + name = "project" + version = "0.1.0" + authors = ["rhysd "] + edition = "2018" + + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + + [dependencies] diff --combined .vim/bundle/vim-lsp-ale/test/integ/project/src/lib.rs index 00000000,8f97f82b..8f97f82b mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/integ/project/src/lib.rs +++ b/.vim/bundle/vim-lsp-ale/test/integ/project/src/lib.rs @@@ -1,0 -1,3 +1,3 @@@ + pub fn do_something() { + let this_variable_is_unused = 42; + } diff --combined .vim/bundle/vim-lsp-ale/test/integ/test.vimspec index 00000000,5ae295bd..5ae295bd mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/integ/test.vimspec +++ b/.vim/bundle/vim-lsp-ale/test/integ/test.vimspec @@@ -1,0 -1,103 +1,103 @@@ + let s:SEP = has('win32') ? '\' : '/' + + function! s:get_debug_info(bufnr) abort + let uri = lsp#utils#get_buffer_uri(a:bufnr) + let all_diags = lsp#internal#diagnostics#state#_get_all_diagnostics_grouped_by_server_for_uri(uri) + return "\nall diags: " . string(all_diags) + \ . "\nlocation list: " . string(ale#engine#GetLoclist(a:bufnr)) + \ . "\nserver_status: " . lsp#get_server_status() + \ . "\ncurrent lines: " . string(getline(1, '$')) + endfunction + + Describe rust-analyzer + Before all + if !executable('rust-analyzer') + throw 'rust-analyzer command is not found. It must be installed for running integration tests' + endif + + let dir = IntegTestRootDir() + execute 'cd' dir + let file = join([dir, 'project', 'src', 'lib.rs'], s:SEP) + + " Note: It might be better to write lib.rs here and delete in `After all` hook rather than + " modifying a file committed to repository directly. + let lib_rs_contents = readfile(file) + End + + After all + " Restore contents of lib.rs since it was modified by test case + call writefile(lib_rs_contents, file) + + redir! > integ_messages.txt + if exists(':LspStatus') + LspStatus + else + echom 'No :LspStatus command is defined' + endif + message + redir END + End + + Before each + execute 'edit!' file + End + + After each + bwipeout! + End + + It shows diagnostics results with ALE through vim-lsp + Assert lsp#ale#enabled() + + let bufnr = bufnr('') + + let elapsed = 0 " in seconds + let timeout = 120 " in seconds + let counts = ale#statusline#Count(bufnr) + while elapsed <= timeout + if counts.total > 0 + break + endif + sleep 1 + let elapsed += 1 + let counts = ale#statusline#Count(bufnr) + endwhile + + let info = s:get_debug_info(bufnr) + Assert True(counts.total > 0, 'No error found after ' . elapsed . ' seconds' . info) + + let loclist = ale#engine#GetLoclist(bufnr) + Assert NotEmpty(loclist, 'Location list from ALE is empty after ' . elapsed . ' seconds. ' . info) + + let item = loclist[0] + let item_str = string(item) + Assert Equals(item.linter_name, 'vim-lsp', item_str . info) + Assert True(item.from_other_source, item_str . info) + Assert Match(item.filename, 'lib\.rs$', item_str . info) + Assert Match(item.text, 'this_variable_is_unused', item_str . info) + + " Fix the problem + normal! ggjdd + write + + let elapsed = 0 " in seconds + let counts = ale#statusline#Count(bufnr) + while elapsed <= timeout + if counts.total == 0 + break + endif + sleep 1 + let elapsed += 1 + let counts = ale#statusline#Count(bufnr) + endwhile + + let info = s:get_debug_info(bufnr) + Assert True(counts.total == 0, 'Error found after ' . elapsed . ' seconds' . info) + + " Check the error was removed from location list since it'd been fixed + let loclist = ale#engine#GetLoclist(bufnr) + Assert Empty(loclist, 'Location list from ALE is not empty after ' . elapsed . ' seconds. ' . info) + End + End + + " vim: set ft=vim: diff --combined .vim/bundle/vim-lsp-ale/test/unit/.themisrc index 00000000,f04b082d..f04b082d mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/unit/.themisrc +++ b/.vim/bundle/vim-lsp-ale/test/unit/.themisrc @@@ -1,0 -1,18 +1,18 @@@ + call themis#option('exclude', 'test/README.md') + + let s:dir = expand(':p:h') + let s:sep = has('win32') ? '\' : '/' + let s:runtime_dir = join([s:dir, 'runtime'], s:sep) + + execute 'set rtp+=' . s:runtime_dir + + let s:helper = themis#helper('assert') + call themis#helper('command').with(s:helper) + + if $THEMIS_PROFILE !=# '' + execute 'profile' 'start' $THEMIS_PROFILE + profile! file ./autoload/lsp/ale.vim + profile! file ./plugin/lsp_ale.vim + endif + + " vim: set ft=vim: diff --combined .vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/ale/other_source.vim index 00000000,dda4fae6..dda4fae6 mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/ale/other_source.vim +++ b/.vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/ale/other_source.vim @@@ -1,0 -1,62 +1,62 @@@ + function! ale#other_source#StartChecking(bufnr, name) abort + let s:start_checking_called = [a:bufnr, a:name] + endfunction + + function! ale#other_source#ShowResults(bufnr, name, results) abort + let s:show_results_called = [a:bufnr, a:name, a:results] + endfunction + + function! ale#other_source#last_start_checking() abort + return s:start_checking_called + endfunction + + function! ale#other_source#last_show_results() abort + return s:show_results_called + endfunction + + function! WaitUntil(func, ...) abort + let timeout = get(a:, 1, 1) " 1sec by default + let total = 0 + while !a:func() + sleep 100m + let total += 0.1 + if total >= timeout + " Note: v:true/v:false are not supported by themis.vim + " https://github.com/thinca/vim-themis/pull/56 + return 0 + endif + endwhile + return 1 + endfunction + + function! ale#other_source#wait_until_show_results() abort + let timeout = 1 + let total = 0 + while s:show_results_called is v:null + let total += 0.1 + if total > timeout + throw 'ale#other_source#ShowResults() was not called while 1 second' + endif + sleep 100m + endwhile + endfunction + + function! ale#other_source#check_show_no_result() abort + let timeout = 1 + let total = 0 + while s:show_results_called is v:null + let total += 0.1 + if total > timeout + return + endif + sleep 100m + endwhile + throw 'ale#other_source#ShowResults() was called within 1 second: ' . string(s:show_results_called) + endfunction + + function! ale#other_source#reset() abort + let s:start_checking_called = v:null + let s:show_results_called = v:null + endfunction + + call ale#other_source#reset() diff --combined .vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/lsp.vim index 00000000,64d078b3..64d078b3 mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/lsp.vim +++ b/.vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/lsp.vim @@@ -1,0 -1,2 +1,2 @@@ + function! lsp#stream() abort + endfunction diff --combined .vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/lsp/callbag.vim index 00000000,9d3b35fe..9d3b35fe mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/lsp/callbag.vim +++ b/.vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/lsp/callbag.vim @@@ -1,0 -1,35 +1,35 @@@ + function! lsp#callbag#pipe(source, filter, sink) abort + let s:Filter = a:filter + let s:Next = a:sink.next + return {-> extend(s:, {'disposed': v:true})} + endfunction + + function! lsp#callbag#filter(pred) abort + return a:pred + endfunction + + function! lsp#callbag#subscribe(sink) abort + return a:sink + endfunction + + " Functions for tests + + function! lsp#callbag#piped() abort + return s:Filter isnot v:null && s:Next isnot v:null + endfunction + + function! lsp#callbag#disposed() abort + return s:disposed + endfunction + + function! lsp#callbag#reset() abort + let s:Filter = v:null + let s:Next = v:null + let s:disposed = v:false + endfunction + + function! lsp#callbag#mock_receive(res) abort + if s:Filter(a:res) + call s:Next(a:res) + endif + endfunction diff --combined .vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/lsp/internal/diagnostics/state.vim index 00000000,e492cf29..e492cf29 mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/lsp/internal/diagnostics/state.vim +++ b/.vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/lsp/internal/diagnostics/state.vim @@@ -1,0 -1,7 +1,7 @@@ + function! lsp#internal#diagnostics#state#_is_enabled_for_buffer(bufnr) abort + return a:bufnr == g:lsp_ale_test_mock_bufnr + endfunction + + function! lsp#internal#diagnostics#state#_get_all_diagnostics_grouped_by_server_for_uri(uri) abort + return g:lsp_ale_test_mock_diags + endfunction diff --combined .vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/lsp/ui/vim/utils.vim index 00000000,3236f170..3236f170 mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/lsp/ui/vim/utils.vim +++ b/.vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/lsp/ui/vim/utils.vim @@@ -1,0 -1,19 +1,19 @@@ + function! lsp#ui#vim#utils#diagnostics_to_loc_list(res) abort + if len(s:loclists) == 0 + return [] + endif + + let ret = s:loclists[0] + let s:loclists = s:loclists[1:] + return ret + endfunction + + function! lsp#ui#vim#utils#mock_diagnostics_to_loc_list(loclists) abort + let s:loclists = copy(a:loclists) + endfunction + + function! lsp#ui#vim#utils#reset() abort + let s:loclists = [] + endfunction + + call lsp#ui#vim#utils#reset() diff --combined .vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/lsp/utils.vim index 00000000,c8dcd35f..c8dcd35f mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/lsp/utils.vim +++ b/.vim/bundle/vim-lsp-ale/test/unit/runtime/autoload/lsp/utils.vim @@@ -1,0 -1,11 +1,11 @@@ + function! lsp#utils#get_buffer_uri(bufnr) abort + return 'file://' . s:bufname + endfunction + + function! lsp#utils#uri_to_path(uri) abort + return s:bufname + endfunction + + function! lsp#utils#mock_buf_name(name) abort + let s:bufname = a:name + endfunction diff --combined .vim/bundle/vim-lsp-ale/test/unit/test.vimspec index 00000000,cbe57d39..cbe57d39 mode 000000,100644..100644 --- a/.vim/bundle/vim-lsp-ale/test/unit/test.vimspec +++ b/.vim/bundle/vim-lsp-ale/test/unit/test.vimspec @@@ -1,0 -1,471 +1,471 @@@ + function! s:test_diags() abort + return { + \ 'gopls': { + \ 'method': 'textDocument/publishDiagnostics', + \ 'jsonrpc': '2.0', + \ 'params': { + \ 'uri': 'file:///path/to/dummy.txt', + \ 'diagnostics': [ + \ { + \ 'source': 'compiler', + \ 'range': { + \ 'end': {'character': 4, 'line': 4}, + \ 'start': {'character': 1, 'line': 4} + \ }, + \ 'message': 'error message 1', + \ 'severity': 1 + \ }, + \ { + \ 'source': 'compiler', + \ 'range': { + \ 'end': {'character': 4, 'line': 4}, + \ 'start': {'character': 1, 'line': 4} + \ }, + \ 'message': 'warning message 1', + \ 'severity': 2 + \ } + \ ] + \ } + \ } + \} + endfunction + + function! s:test_locs() abort + return [[ + \ { + \ 'lnum': 5, + \ 'col': 2, + \ 'filename': '/path/to/dummy.txt', + \ 'text': 'compiler:Error:error message 1' + \ }, + \ { + \ 'lnum': 5, + \ 'col': 2, + \ 'filename': '/path/to/dummy.txt', + \ 'text': 'compiler:Warning:warning message 1' + \ } + \ ]] + endfunction + + function! s:test_diags_all_severities() abort + let diags = s:test_diags() + let diag = diags.gopls.params.diagnostics[0] + let diags.gopls.params.diagnostics = [] + for [sev, name] in [[1, 'error'], [2, 'warning'], [3, 'info'], [4, 'hint']] + let d = copy(diag) + let d.severity = sev + let d.message = name . ' message' + let diags.gopls.params.diagnostics += [d] + endfor + return diags + endfunction + + function! s:test_locs_all_severities() abort + let loc = s:test_locs()[0][0] + let locs = [] + for [sev, name] in [[1, 'Error'], [2, 'Warning'], [3, 'Info'], [4, 'Hint']] + let l = copy(loc) + let l.text = 'compiler:' . name . ':' . tolower(name) . ' message' + let locs += [l] + endfor + return [locs] + endfunction + + function! s:test_expected_locs_all_severities() abort + let loc = s:test_locs()[0][0] + let locs = [] + for [sev, name, type] in [[1, 'Error', 'E'], [2, 'Warning', 'W'], [3, 'Info', 'I'], [4, 'Hint', 'H']] + let l = copy(loc) + let l.type = type + let l.text = '[gopls] compiler:' . name . ':' . tolower(name) . ' message' + let locs += [l] + endfor + return locs + endfunction + + function! s:modify_loc_item(item, type) abort + let a:item.type = a:type + let a:item.text = '[gopls] ' . a:item.text + return a:item + endfunction + + Describe vim-lsp-ale + Before all + " Set bufffer name to 'foo' + file /path/to/dummy.txt + End + + Before each + call lsp#ale#_reset_prev_num_diags() + call lsp#callbag#reset() + call ale#other_source#reset() + call lsp#ui#vim#utils#reset() + call lsp#utils#mock_buf_name('/path/to/dummy.txt') + let g:lsp_ale_test_mock_diags = {} + let g:lsp_ale_test_mock_bufnr = bufnr('') + doautocmd User lsp_setup + let g:ale_want_results_buffer = bufnr('') + End + + After each + call lsp#ale#disable() + End + + It enables vim-lsp's diagnostics and disables to output diagnostics + Assert True(g:lsp_diagnostics_enabled) + Assert False(g:lsp_diagnostics_highlights_enabled) + Assert False(g:lsp_diagnostics_signs_enabled) + Assert False(g:lsp_diagnostics_echo_cursor) + Assert False(g:lsp_diagnostics_virtual_text_enabled) + End + + It disables ALE's LSP support + Assert True(g:ale_disable_lsp) + End + + It defines plugin-lsp-ale autocmd group + Assert True(exists('g:loaded_lsp_ale')) + + redir => autocmds + autocmd plugin-lsp-ale + redir END + + Assert True(stridx(autocmds, 'lsp_setup') >= 0, autocmds) + Assert True(stridx(autocmds, 'ALEWantResults') >= 0, autocmds) + End + + It subscribes notification stream on lsp_setup autocmd event + Assert True(lsp#callbag#piped()) + End + + It stops subscribing stream when lsp#ale#disable() is called + call lsp#ale#enable() + Assert True(lsp#ale#enabled()) + call lsp#ale#disable() + Assert False(lsp#ale#enabled()) + Assert True(lsp#callbag#disposed()) + call lsp#ale#disable() + Assert False(lsp#ale#enabled()) + End + + Context ALEWantResults + It does not notify results when vim-lsp-ale is disabled + call lsp#ale#disable() + doautocmd User ALEWantResults + Assert Equals(ale#other_source#last_start_checking(), v:null) + End + + It does not notify results when the buffer disables LSP + Assert Equals(ale#other_source#last_start_checking(), v:null) + + let g:lsp_ale_test_mock_bufnr = -1 + doautocmd User ALEWantResults + + Assert Equals(ale#other_source#last_start_checking(), v:null) + End + + It does not notify on no diagnostics error + Assert Equals(ale#other_source#last_start_checking(), v:null) + Assert Equals(ale#other_source#last_show_results(), v:null) + + let g:lsp_ale_test_mock_diags = {} + + let bufnr = bufnr('') + doautocmd User ALEWantResults + + call ale#other_source#check_show_no_result() + + Assert Equals(ale#other_source#last_start_checking(), v:null) + Assert Equals(ale#other_source#last_show_results(), v:null) + End + + It notifies location list items converted from diagnostics results + Assert Equals(ale#other_source#last_start_checking(), v:null) + Assert Equals(ale#other_source#last_show_results(), v:null) + + call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs()) + let g:lsp_ale_test_mock_diags = s:test_diags() + + let bufnr = bufnr('') + doautocmd User ALEWantResults + + call ale#other_source#wait_until_show_results() + + Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) + + let [show_bufnr, show_name, loclist] = ale#other_source#last_show_results() + Assert Equals(show_bufnr, bufnr) + Assert Equals(show_name, 'vim-lsp') + + let expected_locs = s:test_locs()[0] + call s:modify_loc_item(expected_locs[0], 'E') + call s:modify_loc_item(expected_locs[1], 'W') + + Assert Equals(loclist, expected_locs) + End + + It filters diagnostics results by severity + Assert Equals(ale#other_source#last_start_checking(), v:null) + Assert Equals(ale#other_source#last_show_results(), v:null) + + call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs()) + let actual_diags = s:test_diags() + " Set 'hint' severity. Default threshold is 'info' + let actual_diags.gopls.params.diagnostics[1].severity = 4 + let g:lsp_ale_test_mock_diags = actual_diags + + let bufnr = bufnr('') + doautocmd User ALEWantResults + + call ale#other_source#wait_until_show_results() + + Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) + + let [show_bufnr, show_name, loclist] = ale#other_source#last_show_results() + Assert Equals(show_bufnr, bufnr) + Assert Equals(show_name, 'vim-lsp') + + Assert Equals(len(loclist), 1, string(loclist)) + End + + It skips notifying results to ALE when no error continues to happen + let bufnr = bufnr('') + + " Prepare empty results + let diags = s:test_diags() + let diags.gopls.params.diagnostics = [] + let g:lsp_ale_test_mock_diags = diags + + " First notification + doautocmd User ALEWantResults + + call ale#other_source#wait_until_show_results() + Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) + Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', []]) + + call ale#other_source#reset() + + " Second notification + doautocmd User ALEWantResults + + call ale#other_source#check_show_no_result() + Assert Equals(ale#other_source#last_start_checking(), v:null) + End + End + + Context textDocument/publishDiagnostics notification + It notifies diagnostics results to ALE + Assert Equals(ale#other_source#last_start_checking(), v:null) + Assert Equals(ale#other_source#last_show_results(), v:null) + + let bufnr = bufnr('') + call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs()) + let g:lsp_ale_test_mock_diags = s:test_diags() + + let response = { 'response': s:test_diags()['gopls'], 'server': 'gopls' } + call lsp#callbag#mock_receive(response) + + call ale#other_source#wait_until_show_results() + + Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) + + let [show_bufnr, show_name, loclist] = ale#other_source#last_show_results() + Assert Equals(show_bufnr, bufnr) + Assert Equals(show_name, 'vim-lsp') + + let expected_locs = s:test_locs()[0] + call s:modify_loc_item(expected_locs[0], 'E') + call s:modify_loc_item(expected_locs[1], 'W') + + Assert Equals(loclist, expected_locs) + End + + It does nothing when receiving notification other than textDocument/publishDiagnostics + call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs()) + let g:lsp_ale_test_mock_diags = s:test_diags() + let response = { + \ 'server': 'gopls', + \ 'response': { + \ 'method': 'something/doSomethihg', + \ 'jsonrpc': '2.0', + \ 'params': {}, + \ } + \ } + call lsp#callbag#mock_receive(response) + + call ale#other_source#check_show_no_result() + Assert Equals(ale#other_source#last_start_checking(), v:null) + End + + It does nothing when method or server is missing in the notification + call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs()) + let g:lsp_ale_test_mock_diags = s:test_diags() + + for response in [ + \ { + \ 'response': { + \ 'method': 'something/doSomethihg', + \ 'jsonrpc': '2.0', + \ 'params': {}, + \ } + \ }, + \ { + \ 'server': 'gopls', + \ 'response': { + \ 'jsonrpc': '2.0', + \ 'params': {}, + \ } + \ } + \ ] + call lsp#callbag#mock_receive(response) + endfor + + call ale#other_source#check_show_no_result() + Assert Equals(ale#other_source#last_start_checking(), v:null) + End + + It does nothing when received notification is for buffer which doesn't exist + let bufnr = bufnr('') + call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs()) + let g:lsp_ale_test_mock_diags = s:test_diags() + call lsp#utils#mock_buf_name('/path/to/somewhere/else.txt') + + let response = { 'response': s:test_diags()['gopls'], 'server': 'gopls' } + call lsp#callbag#mock_receive(response) + + call ale#other_source#check_show_no_result() + Assert Equals(ale#other_source#last_start_checking(), v:null) + End + + It notifies empty list when notification says no lint error was found + let bufnr = bufnr('') + let response = { 'response': s:test_diags()['gopls'], 'server': 'gopls' } + let response.response.params.diagnostics = [] + + call lsp#callbag#mock_receive(response) + + call ale#other_source#wait_until_show_results() + + Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) + Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', []]) + End + + It skips sending results to ALE when no error continues to happen + let bufnr = bufnr('') + let diags = s:test_diags() + let diags.gopls.params.diagnostics = [] + + " First notification + let response = { 'response': diags.gopls, 'server': 'gopls' } + call lsp#callbag#mock_receive(response) + + call ale#other_source#wait_until_show_results() + Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) + Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', []]) + + call ale#other_source#reset() + + " Second notification + call lsp#callbag#mock_receive(response) + + call ale#other_source#check_show_no_result() + Assert Equals(ale#other_source#last_start_checking(), v:null) + End + End + + Describe g:lsp_ale_diagnostics_severity + Before + let saved_diagnostics_severity = g:lsp_ale_diagnostics_severity + End + + After + let g:lsp_ale_diagnostics_severity = saved_diagnostics_severity + End + + It filters results by severity 'error' + let g:lsp_ale_diagnostics_severity = 'error' + + call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs_all_severities()) + let g:lsp_ale_test_mock_diags = s:test_diags_all_severities() + + let bufnr = bufnr('') + doautocmd User ALEWantResults + call ale#other_source#wait_until_show_results() + + Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) + let expected = s:test_expected_locs_all_severities() + call filter(expected, {_, l -> l.type ==# 'E'}) + Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', expected]) + End + + It filters results by severity 'warning' + let g:lsp_ale_diagnostics_severity = 'warning' + + call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs_all_severities()) + let g:lsp_ale_test_mock_diags = s:test_diags_all_severities() + + let bufnr = bufnr('') + doautocmd User ALEWantResults + call ale#other_source#wait_until_show_results() + + Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) + let expected = s:test_expected_locs_all_severities() + call filter(expected, {_, l -> l.type =~# 'E\|W'}) + Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', expected]) + End + + It filters results by severity 'information' + let g:lsp_ale_diagnostics_severity = 'information' + + call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs_all_severities()) + let g:lsp_ale_test_mock_diags = s:test_diags_all_severities() + + let bufnr = bufnr('') + doautocmd User ALEWantResults + call ale#other_source#wait_until_show_results() + + Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) + let expected = s:test_expected_locs_all_severities() + call filter(expected, {_, l -> l.type =~# 'E\|W\|I'}) + Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', expected]) + End + + It filters results by severity 'hint' + let g:lsp_ale_diagnostics_severity = 'hint' + + call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs_all_severities()) + let g:lsp_ale_test_mock_diags = s:test_diags_all_severities() + + let bufnr = bufnr('') + doautocmd User ALEWantResults + call ale#other_source#wait_until_show_results() + + Assert Equals(ale#other_source#last_start_checking(), [bufnr, 'vim-lsp']) + let expected = s:test_expected_locs_all_severities() + Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', expected]) + End + + It throws an error when invalid value is set + let g:lsp_ale_diagnostics_severity = 'invalid!' + let bufnr = bufnr('') + + call lsp#ui#vim#utils#mock_diagnostics_to_loc_list(s:test_locs()) + let g:lsp_ale_test_mock_diags = s:test_diags() + + call lsp#callbag#mock_receive({ 'response': s:test_diags().gopls, 'server': 'gopls' }) + + if has('nvim') + Throws /^vim-lsp-ale: Unexpected severity/ ale#other_source#wait_until_show_results() + else + " XXX: No way to catch exception thrown while sleeping. Indirectly + " check the error was handled correctly by checking the result is + " set to empty. + call ale#other_source#wait_until_show_results() + Assert Equals(ale#other_source#last_show_results(), [bufnr, 'vim-lsp', []]) + endif + End + End + + End + + " vim: set ft=vim: