I broke up with neovim....vim is my best friend now

This commit is contained in:
LinlyBoi
2023-04-30 08:14:07 +03:00
parent 0d185449c5
commit 4a4a6b1e81
5245 changed files with 468325 additions and 25 deletions

View File

@@ -0,0 +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.

View File

@@ -0,0 +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.
<img alt="screencast" src="https://github.com/rhysd/ss/blob/master/vim-lsp-ale/main.gif?raw=true" width="582" height="316"/>
## 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

View File

@@ -0,0 +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

View File

@@ -0,0 +1,17 @@
g:lsp_ale_auto_config_ale vim-lsp-ale.txt /*g:lsp_ale_auto_config_ale*
g:lsp_ale_auto_config_vim_lsp vim-lsp-ale.txt /*g:lsp_ale_auto_config_vim_lsp*
g:lsp_ale_auto_enable_linter vim-lsp-ale.txt /*g:lsp_ale_auto_enable_linter*
g:lsp_ale_diagnostics_severity vim-lsp-ale.txt /*g:lsp_ale_diagnostics_severity*
lsp#ale#disable vim-lsp-ale.txt /*lsp#ale#disable*
lsp#ale#enable vim-lsp-ale.txt /*lsp#ale#enable*
lsp#ale#enabled vim-lsp-ale.txt /*lsp#ale#enabled*
vim-lsp-ale vim-lsp-ale.txt /*vim-lsp-ale*
vim-lsp-ale-contents vim-lsp-ale.txt /*vim-lsp-ale-contents*
vim-lsp-ale-functions vim-lsp-ale.txt /*vim-lsp-ale-functions*
vim-lsp-ale-install vim-lsp-ale.txt /*vim-lsp-ale-install*
vim-lsp-ale-introduction vim-lsp-ale.txt /*vim-lsp-ale-introduction*
vim-lsp-ale-issues vim-lsp-ale.txt /*vim-lsp-ale-issues*
vim-lsp-ale-license vim-lsp-ale.txt /*vim-lsp-ale-license*
vim-lsp-ale-usage vim-lsp-ale.txt /*vim-lsp-ale-usage*
vim-lsp-ale-variables vim-lsp-ale.txt /*vim-lsp-ale-variables*
vim-lsp-ale.txt vim-lsp-ale.txt /*vim-lsp-ale.txt*

View File

@@ -0,0 +1,213 @@
*vim-lsp-ale.txt* Bridge between vim-lsp and ALE
Author: rhysd <https://rhysd.github.io>
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:

View File

@@ -0,0 +1,8 @@
coverage:
status:
project:
default:
target: 0%
patch:
default:
target: 0%

View File

@@ -0,0 +1,3 @@
[run]
plugins = covimerage
data_file = .coverage_covimerage

View File

@@ -0,0 +1 @@
ref: refs/heads/master

View File

@@ -0,0 +1,11 @@
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
[remote "origin"]
url = https://github.com/rhysd/vim-lsp-ale.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master

View File

@@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.

View File

@@ -0,0 +1,15 @@
#!/bin/sh
#
# An example hook script to check the commit log message taken by
# applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit. The hook is
# allowed to edit the commit message file.
#
# To enable this hook, rename this file to "applypatch-msg".
. git-sh-setup
commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
:

View File

@@ -0,0 +1,24 @@
#!/bin/sh
#
# An example hook script to check the commit log message.
# Called by "git commit" with one argument, the name of the file
# that has the commit message. The hook should exit with non-zero
# status after issuing an appropriate message if it wants to stop the
# commit. The hook is allowed to edit the commit message file.
#
# To enable this hook, rename this file to "commit-msg".
# Uncomment the below to add a Signed-off-by line to the message.
# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
# hook is more suited to it.
#
# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
# This example catches duplicate Signed-off-by lines.
test "" = "$(grep '^Signed-off-by: ' "$1" |
sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
echo >&2 Duplicate Signed-off-by lines.
exit 1
}

View File

@@ -0,0 +1,174 @@
#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open2;
# An example hook script to integrate Watchman
# (https://facebook.github.io/watchman/) with git to speed up detecting
# new and modified files.
#
# The hook is passed a version (currently 2) and last update token
# formatted as a string and outputs to stdout a new update token and
# all files that have been modified since the update token. Paths must
# be relative to the root of the working tree and separated by a single NUL.
#
# To enable this hook, rename this file to "query-watchman" and set
# 'git config core.fsmonitor .git/hooks/query-watchman'
#
my ($version, $last_update_token) = @ARGV;
# Uncomment for debugging
# print STDERR "$0 $version $last_update_token\n";
# Check the hook interface version
if ($version ne 2) {
die "Unsupported query-fsmonitor hook version '$version'.\n" .
"Falling back to scanning...\n";
}
my $git_work_tree = get_working_dir();
my $retry = 1;
my $json_pkg;
eval {
require JSON::XS;
$json_pkg = "JSON::XS";
1;
} or do {
require JSON::PP;
$json_pkg = "JSON::PP";
};
launch_watchman();
sub launch_watchman {
my $o = watchman_query();
if (is_work_tree_watched($o)) {
output_result($o->{clock}, @{$o->{files}});
}
}
sub output_result {
my ($clockid, @files) = @_;
# Uncomment for debugging watchman output
# open (my $fh, ">", ".git/watchman-output.out");
# binmode $fh, ":utf8";
# print $fh "$clockid\n@files\n";
# close $fh;
binmode STDOUT, ":utf8";
print $clockid;
print "\0";
local $, = "\0";
print @files;
}
sub watchman_clock {
my $response = qx/watchman clock "$git_work_tree"/;
die "Failed to get clock id on '$git_work_tree'.\n" .
"Falling back to scanning...\n" if $? != 0;
return $json_pkg->new->utf8->decode($response);
}
sub watchman_query {
my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
or die "open2() failed: $!\n" .
"Falling back to scanning...\n";
# In the query expression below we're asking for names of files that
# changed since $last_update_token but not from the .git folder.
#
# To accomplish this, we're using the "since" generator to use the
# recency index to select candidate nodes and "fields" to limit the
# output to file names only. Then we're using the "expression" term to
# further constrain the results.
my $last_update_line = "";
if (substr($last_update_token, 0, 1) eq "c") {
$last_update_token = "\"$last_update_token\"";
$last_update_line = qq[\n"since": $last_update_token,];
}
my $query = <<" END";
["query", "$git_work_tree", {$last_update_line
"fields": ["name"],
"expression": ["not", ["dirname", ".git"]]
}]
END
# Uncomment for debugging the watchman query
# open (my $fh, ">", ".git/watchman-query.json");
# print $fh $query;
# close $fh;
print CHLD_IN $query;
close CHLD_IN;
my $response = do {local $/; <CHLD_OUT>};
# Uncomment for debugging the watch response
# open ($fh, ">", ".git/watchman-response.json");
# print $fh $response;
# close $fh;
die "Watchman: command returned no output.\n" .
"Falling back to scanning...\n" if $response eq "";
die "Watchman: command returned invalid output: $response\n" .
"Falling back to scanning...\n" unless $response =~ /^\{/;
return $json_pkg->new->utf8->decode($response);
}
sub is_work_tree_watched {
my ($output) = @_;
my $error = $output->{error};
if ($retry > 0 and $error and $error =~ m/unable to resolve root .* directory (.*) is not watched/) {
$retry--;
my $response = qx/watchman watch "$git_work_tree"/;
die "Failed to make watchman watch '$git_work_tree'.\n" .
"Falling back to scanning...\n" if $? != 0;
$output = $json_pkg->new->utf8->decode($response);
$error = $output->{error};
die "Watchman: $error.\n" .
"Falling back to scanning...\n" if $error;
# Uncomment for debugging watchman output
# open (my $fh, ">", ".git/watchman-output.out");
# close $fh;
# Watchman will always return all files on the first query so
# return the fast "everything is dirty" flag to git and do the
# Watchman query just to get it over with now so we won't pay
# the cost in git to look up each individual file.
my $o = watchman_clock();
$error = $output->{error};
die "Watchman: $error.\n" .
"Falling back to scanning...\n" if $error;
output_result($o->{clock}, ("/"));
$last_update_token = $o->{clock};
eval { launch_watchman() };
return 0;
}
die "Watchman: $error.\n" .
"Falling back to scanning...\n" if $error;
return 1;
}
sub get_working_dir {
my $working_dir;
if ($^O =~ 'msys' || $^O =~ 'cygwin') {
$working_dir = Win32::GetCwd();
$working_dir =~ tr/\\/\//;
} else {
require Cwd;
$working_dir = Cwd::cwd();
}
return $working_dir;
}

View File

@@ -0,0 +1,8 @@
#!/bin/sh
#
# An example hook script to prepare a packed repository for use over
# dumb transports.
#
# To enable this hook, rename this file to "post-update".
exec git update-server-info

View File

@@ -0,0 +1,14 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed
# by applypatch from an e-mail message.
#
# The hook should exit with non-zero status after issuing an
# appropriate message if it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-applypatch".
. git-sh-setup
precommit="$(git rev-parse --git-path hooks/pre-commit)"
test -x "$precommit" && exec "$precommit" ${1+"$@"}
:

View File

@@ -0,0 +1,49 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".
if git rev-parse --verify HEAD >/dev/null 2>&1
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=$(git hash-object -t tree /dev/null)
fi
# If you want to allow non-ASCII filenames set this variable to true.
allownonascii=$(git config --type=bool hooks.allownonascii)
# Redirect output to stderr.
exec 1>&2
# Cross platform projects tend to avoid non-ASCII filenames; prevent
# them from being added to the repository. We exploit the fact that the
# printable range starts at the space character and ends with tilde.
if [ "$allownonascii" != "true" ] &&
# Note that the use of brackets around a tr range is ok here, (it's
# even required, for portability to Solaris 10's /usr/bin/tr), since
# the square bracket bytes happen to fall in the designated range.
test $(git diff --cached --name-only --diff-filter=A -z $against |
LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
then
cat <<\EOF
Error: Attempt to add a non-ASCII file name.
This can cause problems if you want to work with people on other platforms.
To be portable it is advisable to rename the file.
If you know what you are doing you can disable this check using:
git config hooks.allownonascii true
EOF
exit 1
fi
# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --

View File

@@ -0,0 +1,13 @@
#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git merge" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message to
# stderr if it wants to stop the merge commit.
#
# To enable this hook, rename this file to "pre-merge-commit".
. git-sh-setup
test -x "$GIT_DIR/hooks/pre-commit" &&
exec "$GIT_DIR/hooks/pre-commit"
:

View File

@@ -0,0 +1,53 @@
#!/bin/sh
# An example hook script to verify what is about to be pushed. Called by "git
# push" after it has checked the remote status, but before anything has been
# pushed. If this script exits with a non-zero status nothing will be pushed.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
# <local ref> <local oid> <remote ref> <remote oid>
#
# This sample shows how to prevent push of commits where the log message starts
# with "WIP" (work in progress).
remote="$1"
url="$2"
zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
while read local_ref local_oid remote_ref remote_oid
do
if test "$local_oid" = "$zero"
then
# Handle delete
:
else
if test "$remote_oid" = "$zero"
then
# New branch, examine all commits
range="$local_oid"
else
# Update to existing branch, examine new commits
range="$remote_oid..$local_oid"
fi
# Check for WIP commit
commit=$(git rev-list -n 1 --grep '^WIP' "$range")
if test -n "$commit"
then
echo >&2 "Found WIP commit in $local_ref, not pushing"
exit 1
fi
fi
done
exit 0

View File

@@ -0,0 +1,169 @@
#!/bin/sh
#
# Copyright (c) 2006, 2008 Junio C Hamano
#
# The "pre-rebase" hook is run just before "git rebase" starts doing
# its job, and can prevent the command from running by exiting with
# non-zero status.
#
# The hook is called with the following parameters:
#
# $1 -- the upstream the series was forked from.
# $2 -- the branch being rebased (or empty when rebasing the current branch).
#
# This sample shows how to prevent topic branches that are already
# merged to 'next' branch from getting rebased, because allowing it
# would result in rebasing already published history.
publish=next
basebranch="$1"
if test "$#" = 2
then
topic="refs/heads/$2"
else
topic=`git symbolic-ref HEAD` ||
exit 0 ;# we do not interrupt rebasing detached HEAD
fi
case "$topic" in
refs/heads/??/*)
;;
*)
exit 0 ;# we do not interrupt others.
;;
esac
# Now we are dealing with a topic branch being rebased
# on top of master. Is it OK to rebase it?
# Does the topic really exist?
git show-ref -q "$topic" || {
echo >&2 "No such branch $topic"
exit 1
}
# Is topic fully merged to master?
not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
if test -z "$not_in_master"
then
echo >&2 "$topic is fully merged to master; better remove it."
exit 1 ;# we could allow it, but there is no point.
fi
# Is topic ever merged to next? If so you should not be rebasing it.
only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
only_next_2=`git rev-list ^master ${publish} | sort`
if test "$only_next_1" = "$only_next_2"
then
not_in_topic=`git rev-list "^$topic" master`
if test -z "$not_in_topic"
then
echo >&2 "$topic is already up to date with master"
exit 1 ;# we could allow it, but there is no point.
else
exit 0
fi
else
not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
/usr/bin/perl -e '
my $topic = $ARGV[0];
my $msg = "* $topic has commits already merged to public branch:\n";
my (%not_in_next) = map {
/^([0-9a-f]+) /;
($1 => 1);
} split(/\n/, $ARGV[1]);
for my $elem (map {
/^([0-9a-f]+) (.*)$/;
[$1 => $2];
} split(/\n/, $ARGV[2])) {
if (!exists $not_in_next{$elem->[0]}) {
if ($msg) {
print STDERR $msg;
undef $msg;
}
print STDERR " $elem->[1]\n";
}
}
' "$topic" "$not_in_next" "$not_in_master"
exit 1
fi
<<\DOC_END
This sample hook safeguards topic branches that have been
published from being rewound.
The workflow assumed here is:
* Once a topic branch forks from "master", "master" is never
merged into it again (either directly or indirectly).
* Once a topic branch is fully cooked and merged into "master",
it is deleted. If you need to build on top of it to correct
earlier mistakes, a new topic branch is created by forking at
the tip of the "master". This is not strictly necessary, but
it makes it easier to keep your history simple.
* Whenever you need to test or publish your changes to topic
branches, merge them into "next" branch.
The script, being an example, hardcodes the publish branch name
to be "next", but it is trivial to make it configurable via
$GIT_DIR/config mechanism.
With this workflow, you would want to know:
(1) ... if a topic branch has ever been merged to "next". Young
topic branches can have stupid mistakes you would rather
clean up before publishing, and things that have not been
merged into other branches can be easily rebased without
affecting other people. But once it is published, you would
not want to rewind it.
(2) ... if a topic branch has been fully merged to "master".
Then you can delete it. More importantly, you should not
build on top of it -- other people may already want to
change things related to the topic as patches against your
"master", so if you need further changes, it is better to
fork the topic (perhaps with the same name) afresh from the
tip of "master".
Let's look at this example:
o---o---o---o---o---o---o---o---o---o "next"
/ / / /
/ a---a---b A / /
/ / / /
/ / c---c---c---c B /
/ / / \ /
/ / / b---b C \ /
/ / / / \ /
---o---o---o---o---o---o---o---o---o---o---o "master"
A, B and C are topic branches.
* A has one fix since it was merged up to "next".
* B has finished. It has been fully merged up to "master" and "next",
and is ready to be deleted.
* C has not merged to "next" at all.
We would want to allow C to be rebased, refuse A, and encourage
B to be deleted.
To compute (1):
git rev-list ^master ^topic next
git rev-list ^master next
if these match, topic has not merged in next at all.
To compute (2):
git rev-list master..topic
if this is empty, it is fully merged to "master".
DOC_END

View File

@@ -0,0 +1,24 @@
#!/bin/sh
#
# An example hook script to make use of push options.
# The example simply echoes all push options that start with 'echoback='
# and rejects all pushes when the "reject" push option is used.
#
# To enable this hook, rename this file to "pre-receive".
if test -n "$GIT_PUSH_OPTION_COUNT"
then
i=0
while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
do
eval "value=\$GIT_PUSH_OPTION_$i"
case "$value" in
echoback=*)
echo "echo from the pre-receive-hook: ${value#*=}" >&2
;;
reject)
exit 1
esac
i=$((i + 1))
done
fi

View File

@@ -0,0 +1,42 @@
#!/bin/sh
#
# An example hook script to prepare the commit log message.
# Called by "git commit" with the name of the file that has the
# commit message, followed by the description of the commit
# message's source. The hook's purpose is to edit the commit
# message file. If the hook fails with a non-zero status,
# the commit is aborted.
#
# To enable this hook, rename this file to "prepare-commit-msg".
# This hook includes three examples. The first one removes the
# "# Please enter the commit message..." help message.
#
# The second includes the output of "git diff --name-status -r"
# into the message, just before the "git status" output. It is
# commented because it doesn't cope with --amend or with squashed
# commits.
#
# The third example adds a Signed-off-by line to the message, that can
# still be edited. This is rarely a good idea.
COMMIT_MSG_FILE=$1
COMMIT_SOURCE=$2
SHA1=$3
/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
# case "$COMMIT_SOURCE,$SHA1" in
# ,|template,)
# /usr/bin/perl -i.bak -pe '
# print "\n" . `git diff --cached --name-status -r`
# if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
# *) ;;
# esac
# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
# if test -z "$COMMIT_SOURCE"
# then
# /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
# fi

View File

@@ -0,0 +1,78 @@
#!/bin/sh
# An example hook script to update a checked-out tree on a git push.
#
# This hook is invoked by git-receive-pack(1) when it reacts to git
# push and updates reference(s) in its repository, and when the push
# tries to update the branch that is currently checked out and the
# receive.denyCurrentBranch configuration variable is set to
# updateInstead.
#
# By default, such a push is refused if the working tree and the index
# of the remote repository has any difference from the currently
# checked out commit; when both the working tree and the index match
# the current commit, they are updated to match the newly pushed tip
# of the branch. This hook is to be used to override the default
# behaviour; however the code below reimplements the default behaviour
# as a starting point for convenient modification.
#
# The hook receives the commit with which the tip of the current
# branch is going to be updated:
commit=$1
# It can exit with a non-zero status to refuse the push (when it does
# so, it must not modify the index or the working tree).
die () {
echo >&2 "$*"
exit 1
}
# Or it can make any necessary changes to the working tree and to the
# index to bring them to the desired state when the tip of the current
# branch is updated to the new commit, and exit with a zero status.
#
# For example, the hook can simply run git read-tree -u -m HEAD "$1"
# in order to emulate git fetch that is run in the reverse direction
# with git push, as the two-tree form of git read-tree -u -m is
# essentially the same as git switch or git checkout that switches
# branches while keeping the local changes in the working tree that do
# not interfere with the difference between the branches.
# The below is a more-or-less exact translation to shell of the C code
# for the default behaviour for git's push-to-checkout hook defined in
# the push_to_deploy() function in builtin/receive-pack.c.
#
# Note that the hook will be executed from the repository directory,
# not from the working tree, so if you want to perform operations on
# the working tree, you will have to adapt your code accordingly, e.g.
# by adding "cd .." or using relative paths.
if ! git update-index -q --ignore-submodules --refresh
then
die "Up-to-date check failed"
fi
if ! git diff-files --quiet --ignore-submodules --
then
die "Working directory has unstaged changes"
fi
# This is a rough translation of:
#
# head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX
if git cat-file -e HEAD 2>/dev/null
then
head=HEAD
else
head=$(git hash-object -t tree --stdin </dev/null)
fi
if ! git diff-index --quiet --cached --ignore-submodules $head --
then
die "Working directory has staged changes"
fi
if ! git read-tree -u -m "$commit"
then
die "Could not update working tree to new HEAD"
fi

View File

@@ -0,0 +1,128 @@
#!/bin/sh
#
# An example hook script to block unannotated tags from entering.
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
#
# To enable this hook, rename this file to "update".
#
# Config
# ------
# hooks.allowunannotated
# This boolean sets whether unannotated tags will be allowed into the
# repository. By default they won't be.
# hooks.allowdeletetag
# This boolean sets whether deleting tags will be allowed in the
# repository. By default they won't be.
# hooks.allowmodifytag
# This boolean sets whether a tag may be modified after creation. By default
# it won't be.
# hooks.allowdeletebranch
# This boolean sets whether deleting branches will be allowed in the
# repository. By default they won't be.
# hooks.denycreatebranch
# This boolean sets whether remotely creating branches will be denied
# in the repository. By default this is allowed.
#
# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"
# --- Safety check
if [ -z "$GIT_DIR" ]; then
echo "Don't run this script from the command line." >&2
echo " (if you want, you could supply GIT_DIR then run" >&2
echo " $0 <ref> <oldrev> <newrev>)" >&2
exit 1
fi
if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
echo "usage: $0 <ref> <oldrev> <newrev>" >&2
exit 1
fi
# --- Config
allowunannotated=$(git config --type=bool hooks.allowunannotated)
allowdeletebranch=$(git config --type=bool hooks.allowdeletebranch)
denycreatebranch=$(git config --type=bool hooks.denycreatebranch)
allowdeletetag=$(git config --type=bool hooks.allowdeletetag)
allowmodifytag=$(git config --type=bool hooks.allowmodifytag)
# check for no description
projectdesc=$(sed -e '1q' "$GIT_DIR/description")
case "$projectdesc" in
"Unnamed repository"* | "")
echo "*** Project description file hasn't been set" >&2
exit 1
;;
esac
# --- Check types
# if $newrev is 0000...0000, it's a commit to delete a ref.
zero=$(git hash-object --stdin </dev/null | tr '[0-9a-f]' '0')
if [ "$newrev" = "$zero" ]; then
newrev_type=delete
else
newrev_type=$(git cat-file -t $newrev)
fi
case "$refname","$newrev_type" in
refs/tags/*,commit)
# un-annotated tag
short_refname=${refname##refs/tags/}
if [ "$allowunannotated" != "true" ]; then
echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
exit 1
fi
;;
refs/tags/*,delete)
# delete tag
if [ "$allowdeletetag" != "true" ]; then
echo "*** Deleting a tag is not allowed in this repository" >&2
exit 1
fi
;;
refs/tags/*,tag)
# annotated tag
if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
then
echo "*** Tag '$refname' already exists." >&2
echo "*** Modifying a tag is not allowed in this repository." >&2
exit 1
fi
;;
refs/heads/*,commit)
# branch
if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
echo "*** Creating a branch is not allowed in this repository" >&2
exit 1
fi
;;
refs/heads/*,delete)
# delete branch
if [ "$allowdeletebranch" != "true" ]; then
echo "*** Deleting a branch is not allowed in this repository" >&2
exit 1
fi
;;
refs/remotes/*,commit)
# tracking branch
;;
refs/remotes/*,delete)
# delete tracking branch
if [ "$allowdeletebranch" != "true" ]; then
echo "*** Deleting a tracking branch is not allowed in this repository" >&2
exit 1
fi
;;
*)
# Anything else (is there anything else?)
echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
exit 1
;;
esac
# --- Finished
exit 0

Binary file not shown.

View File

@@ -0,0 +1,6 @@
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

View File

@@ -0,0 +1,2 @@
0000000000000000000000000000000000000000 db0f9a8a33c0480988dc420cd2fba8a07743e4a4 LinlyBoi <libkyy@e.email> 1676062730 +0200 clone: from https://github.com/rhysd/vim-lsp-ale.git
db0f9a8a33c0480988dc420cd2fba8a07743e4a4 db0f9a8a33c0480988dc420cd2fba8a07743e4a4 LinlyBoi <libkyy@e.email> 1676062732 +0200 checkout: moving from master to master

View File

@@ -0,0 +1 @@
0000000000000000000000000000000000000000 db0f9a8a33c0480988dc420cd2fba8a07743e4a4 LinlyBoi <libkyy@e.email> 1676062730 +0200 clone: from https://github.com/rhysd/vim-lsp-ale.git

View File

@@ -0,0 +1 @@
0000000000000000000000000000000000000000 db0f9a8a33c0480988dc420cd2fba8a07743e4a4 LinlyBoi <libkyy@e.email> 1676062730 +0200 clone: from https://github.com/rhysd/vim-lsp-ale.git

View File

@@ -0,0 +1,2 @@
# pack-refs with: peeled fully-peeled sorted
db0f9a8a33c0480988dc420cd2fba8a07743e4a4 refs/remotes/origin/master

View File

@@ -0,0 +1 @@
db0f9a8a33c0480988dc420cd2fba8a07743e4a4

View File

@@ -0,0 +1 @@
ref: refs/remotes/origin/master

View File

@@ -0,0 +1 @@
db0f9a8a33c0480988dc420cd2fba8a07743e4a4

View File

@@ -0,0 +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

View File

@@ -0,0 +1 @@
/doc/tags

View File

@@ -0,0 +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

View File

@@ -0,0 +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

View File

@@ -0,0 +1,4 @@
/deps/vim-lsp
/deps/ale
/lsp-log.txt
/integ_messages.txt

View File

@@ -0,0 +1,44 @@
call themis#option('exclude', 'test/README.md')
let s:dir = expand('<sfile>: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:

View File

@@ -0,0 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "project"
version = "0.1.0"

View File

@@ -0,0 +1,9 @@
[package]
name = "project"
version = "0.1.0"
authors = ["rhysd <lin90162@yahoo.co.jp>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

View File

@@ -0,0 +1,2 @@
/target
**/*.rs.bk

View File

@@ -0,0 +1,3 @@
pub fn do_something() {
let this_variable_is_unused = 42;
}

View File

@@ -0,0 +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:

View File

@@ -0,0 +1,18 @@
call themis#option('exclude', 'test/README.md')
let s:dir = expand('<sfile>: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:

View File

@@ -0,0 +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()

View File

@@ -0,0 +1,2 @@
function! lsp#stream() abort
endfunction

View File

@@ -0,0 +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

View File

@@ -0,0 +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

View File

@@ -0,0 +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()

View File

@@ -0,0 +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

View File

@@ -0,0 +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: