X-Git-Url: https://git.madduck.net/etc/vim.git/blobdiff_plain/5a4872f466ebd76ddd532bdf2798554421c53df4..fe3919e725e156d751069662d11e38f7b4791de1:/.vim/bundle/vim-lsp/autoload/lsp/internal/diagnostics/virtual_text.vim diff --git a/.vim/bundle/vim-lsp/autoload/lsp/internal/diagnostics/virtual_text.vim b/.vim/bundle/vim-lsp/autoload/lsp/internal/diagnostics/virtual_text.vim new file mode 100644 index 00000000..a343ea54 --- /dev/null +++ b/.vim/bundle/vim-lsp/autoload/lsp/internal/diagnostics/virtual_text.vim @@ -0,0 +1,195 @@ +" internal state for whether it is enabled or not to avoid multiple subscriptions +let s:enabled = 0 +let s:namespace_id = '' " will be set when enabled +let s:severity_sign_names_mapping = { + \ 1: 'LspError', + \ 2: 'LspWarning', + \ 3: 'LspInformation', + \ 4: 'LspHint', + \ } + +if !hlexists('LspErrorVirtualText') + if !hlexists('LspErrorText') + highlight link LspErrorVirtualText Error + else + highlight link LspErrorVirtualText LspErrorText + endif +endif + +if !hlexists('LspWarningVirtualText') + if !hlexists('LspWarningText') + highlight link LspWarningVirtualText Todo + else + highlight link LspWarningVirtualText LspWarningText + endif +endif + +if !hlexists('LspInformationVirtualText') + if !hlexists('LspInformationText') + highlight link LspInformationVirtualText Normal + else + highlight link LspInformationVirtualText LspInformationText + endif +endif + +if !hlexists('LspHintVirtualText') + if !hlexists('LspHintText') + highlight link LspHintVirtualText Normal + else + highlight link LspHintVirtualText LspHintText + endif +endif + +" imports +let s:Buffer = vital#lsp#import('VS.Vim.Buffer') + +function! lsp#internal#diagnostics#virtual_text#_enable() abort + " don't even bother registering if the feature is disabled + if !lsp#utils#_has_nvim_virtual_text() && !lsp#utils#_has_vim_virtual_text() | return | endif + if !g:lsp_diagnostics_virtual_text_enabled | return | endif + + if s:enabled | return | endif + let s:enabled = 1 + + if has('nvim') + if empty(s:namespace_id) + let s:namespace_id = nvim_create_namespace('vim_lsp_diagnostic_virtual_text') + endif + else + if index(prop_type_list(), 'vim_lsp_LspError_virtual_text') ==# -1 + call prop_type_add('vim_lsp_LspError_virtual_text', { 'highlight': 'LspErrorVirtualText' }) + call prop_type_add('vim_lsp_LspWarning_virtual_text', { 'highlight': 'LspWarningVirtualText' }) + call prop_type_add('vim_lsp_LspInformation_virtual_text', { 'highlight': 'LspInformationVirtualText' }) + call prop_type_add('vim_lsp_LspHint_virtual_text', { 'highlight': 'LspHintVirtualText' }) + endif + endif + + let s:Dispose = lsp#callbag#pipe( + \ lsp#callbag#merge( + \ lsp#callbag#pipe( + \ lsp#stream(), + \ lsp#callbag#filter({x->has_key(x, 'server') && has_key(x, 'response') + \ && has_key(x['response'], 'method') && x['response']['method'] ==# '$/vimlsp/lsp_diagnostics_updated' + \ && !lsp#client#is_error(x['response'])}), + \ lsp#callbag#map({x->x['response']['params']}), + \ ), + \ lsp#callbag#pipe( + \ lsp#callbag#fromEvent(['InsertEnter', 'InsertLeave']), + \ lsp#callbag#filter({_->!g:lsp_diagnostics_virtual_text_insert_mode_enabled}), + \ lsp#callbag#map({_->{ 'uri': lsp#utils#get_buffer_uri() }}), + \ ), + \ ), + \ lsp#callbag#filter({_->g:lsp_diagnostics_virtual_text_enabled}), + \ lsp#callbag#debounceTime(g:lsp_diagnostics_virtual_text_delay), + \ lsp#callbag#tap({x->s:clear_virtual_text(x)}), + \ lsp#callbag#tap({x->s:set_virtual_text(x)}), + \ lsp#callbag#subscribe(), + \ ) +endfunction + +function! lsp#internal#diagnostics#virtual_text#_disable() abort + if !s:enabled | return | endif + if exists('s:Dispose') + call s:Dispose() + unlet s:Dispose + endif + call s:clear_all_virtual_text() + let s:enabled = 0 +endfunction + +function! s:clear_all_virtual_text() abort + if has('nvim') + for l:bufnr in nvim_list_bufs() + if bufexists(l:bufnr) && bufloaded(l:bufnr) + call nvim_buf_clear_namespace(l:bufnr, s:namespace_id, 0, -1) + endif + endfor + else + let l:types = ['vim_lsp_LspError_virtual_text', 'vim_lsp_LspWarning_virtual_text', 'vim_lsp_LspInformation_virtual_text', 'vim_lsp_LspHint_virtual_text'] + for l:bufnr in map(copy(getbufinfo()), 'v:val.bufnr') + if lsp#utils#_has_prop_remove_types() + call prop_remove({'types': l:types, 'bufnr': l:bufnr, 'all': v:true}) + else + for l:type in l:types + call prop_remove({'type': l:type, 'bufnr': l:bufnr, 'all': v:true}) + endfor + endif + endfor + endif +endfunction + +" params => { +" server: '' " optional +" uri: '' " optional +" } +function! s:clear_virtual_text(params) abort + " TODO: optimize by looking at params + call s:clear_all_virtual_text() +endfunction + +" params => { +" server: '' " optional +" uri: '' " optional +" } +function! s:set_virtual_text(params) abort + " TODO: optimize by looking at params + if !g:lsp_diagnostics_virtual_text_insert_mode_enabled + if mode()[0] ==# 'i' | return | endif + endif + + if has('nvim') + for l:bufnr in nvim_list_bufs() + if lsp#internal#diagnostics#state#_is_enabled_for_buffer(l:bufnr) && bufexists(l:bufnr) && bufloaded(l:bufnr) + let l:uri = lsp#utils#get_buffer_uri(l:bufnr) + for [l:server, l:diagnostics_response] in items(lsp#internal#diagnostics#state#_get_all_diagnostics_grouped_by_server_for_uri(l:uri)) + call s:place_virtual_text(l:server, l:diagnostics_response, l:bufnr) + endfor + endif + endfor + else + for l:bufnr in map(copy(getbufinfo()), 'v:val.bufnr') + if lsp#internal#diagnostics#state#_is_enabled_for_buffer(l:bufnr) && bufexists(l:bufnr) && bufloaded(l:bufnr) + let l:uri = lsp#utils#get_buffer_uri(l:bufnr) + for [l:server, l:diagnostics_response] in items(lsp#internal#diagnostics#state#_get_all_diagnostics_grouped_by_server_for_uri(l:uri)) + call s:place_virtual_text(l:server, l:diagnostics_response, l:bufnr) + endfor + endif + endfor + endif +endfunction + +function! s:place_virtual_text(server, diagnostics_response, bufnr) abort + let l:linecount = s:Buffer.get_line_count(a:bufnr) + for l:item in lsp#utils#iteratable(a:diagnostics_response['params']['diagnostics']) + let l:line = lsp#utils#position#lsp_line_to_vim(a:bufnr, l:item['range']['start']) + let l:name = get(s:severity_sign_names_mapping, get(l:item, 'severity', 3), 'LspError') + let l:text = g:lsp_diagnostics_virtual_text_prefix . l:item['message'] + + " Some language servers report an unexpected EOF one line past the end + if l:line == l:linecount + 1 + let l:line = l:line - 1 + endif + + if has('nvim') + let l:hl_name = l:name . 'VirtualText' + " need to do -1 for virtual text + call nvim_buf_set_virtual_text(a:bufnr, s:namespace_id, l:line - 1, + \ [[l:text, l:hl_name]], {}) + else + " it's an error to add virtual text on lines that don't exist + " anymore due to async processing, just skip such diagnostics + if l:line <= l:linecount + let l:type = 'vim_lsp_' . l:name . '_virtual_text' + call prop_remove({'all': v:true, 'type': l:type, 'bufnr': a:bufnr}, l:line) + call prop_add( + \ l:line, 0, + \ { + \ 'type': l:type, 'text': l:text, 'bufnr': a:bufnr, + \ 'text_align': g:lsp_diagnostics_virtual_text_align, + \ 'text_padding_left': g:lsp_diagnostics_virtual_text_padding_left, + \ 'text_wrap': g:lsp_diagnostics_virtual_text_wrap, + \ }) + endif + endif + endfor +endfunction