X-Git-Url: https://git.madduck.net/etc/vim.git/blobdiff_plain/5a4872f466ebd76ddd532bdf2798554421c53df4..fe3919e725e156d751069662d11e38f7b4791de1:/.vim/bundle/vim-lsp/autoload/lsp/internal/diagnostics/state.vim diff --git a/.vim/bundle/vim-lsp/autoload/lsp/internal/diagnostics/state.vim b/.vim/bundle/vim-lsp/autoload/lsp/internal/diagnostics/state.vim new file mode 100644 index 00000000..41ffa277 --- /dev/null +++ b/.vim/bundle/vim-lsp/autoload/lsp/internal/diagnostics/state.vim @@ -0,0 +1,173 @@ +" https://microsoft.github.io/language-server-protocol/specifications/specification-current/#diagnostic +" +" Refer to https://github.com/microsoft/language-server-protocol/pull/1019 on normalization of urls. +" { +" 'normalized_uri': { +" 'server_name': { +" 'method': 'textDocument/publishDiagnostics', +" 'params': { +" 'uri': 'uri', " this uri is not normalized and is exactly what server returns +" 'dignostics': [ " array can never be null but can be empty +" https://microsoft.github.io/language-server-protocol/specifications/specification-current/#diagnostic +" { range, message, severity?, code?, codeDesciption?, source?, tags?, relatedInformation?, data? } +" ] +" } +" } +" } +" Note: Do not remove when buffer unloads or doesn't exist since some server +" may send diagnsotics information regardless of textDocument/didOpen. +" buffer state is removed when server exits. +" TODO: reset buffer state when server initializes. ignoring for now for perf. +let s:diagnostics_state = {} + +" internal state for whether it is enabled or not to avoid multiple subscriptions +let s:enabled = 0 + +let s:diagnostic_kinds = { + \ 1: 'error', + \ 2: 'warning', + \ 3: 'information', + \ 4: 'hint', + \ } + +function! lsp#internal#diagnostics#state#_enable() abort + " don't even bother registering if the feature is disabled + if !g:lsp_diagnostics_enabled | return | endif + + if s:enabled | return | endif + let s:enabled = 1 + + call lsp#internal#diagnostics#state#_reset() + + 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') + \ && get(x['response'], 'method', '') ==# 'textDocument/publishDiagnostics'}), + \ lsp#callbag#tap({x->s:on_text_documentation_publish_diagnostics(x['server'], x['response'])}), + \ ), + \ lsp#callbag#pipe( + \ lsp#stream(), + \ lsp#callbag#filter({x->has_key(x, 'server') && has_key(x, 'response') + \ && get(x['response'], 'method', '') ==# '$/vimlsp/lsp_server_exit' }), + \ lsp#callbag#tap({x->s:on_exit(x['response'])}), + \ ), + \ ), + \ lsp#callbag#subscribe(), + \ ) + + call s:notify_diagnostics_update() +endfunction + +function! lsp#internal#diagnostics#state#_disable() abort + if !s:enabled | return | endif + if exists('s:Dispose') + call s:Dispose() + unlet s:Dispose + endif + call lsp#internal#diagnostics#state#_reset() + call s:notify_diagnostics_update() + let s:enabled = 0 +endfunction + +function! lsp#internal#diagnostics#state#_reset() abort + let s:diagnostics_state = {} + let s:diagnostics_disabled_buffers = {} +endfunction + +" callers should always treat the return value as immutable +" @return { +" 'servername': response +" } +function! lsp#internal#diagnostics#state#_get_all_diagnostics_grouped_by_server_for_uri(uri) abort + return get(s:diagnostics_state, lsp#utils#normalize_uri(a:uri), {}) +endfunction + +" callers should always treat the return value as immutable. +" callers should treat uri as normalized via lsp#utils#normalize_uri +" @return { +" 'normalized_uri': { +" 'servername': response +" } +" } +function! lsp#internal#diagnostics#state#_get_all_diagnostics_grouped_by_uri_and_server() abort + return s:diagnostics_state +endfunction + +function! s:on_text_documentation_publish_diagnostics(server, response) abort + if lsp#client#is_error(a:response) | return | endif + let l:normalized_uri = lsp#utils#normalize_uri(a:response['params']['uri']) + if !has_key(s:diagnostics_state, l:normalized_uri) + let s:diagnostics_state[l:normalized_uri] = {} + endif + let s:diagnostics_state[l:normalized_uri][a:server] = a:response + call s:notify_diagnostics_update(a:server, l:normalized_uri) +endfunction + +function! s:on_exit(response) abort + let l:server = a:response['params']['server'] + let l:notify = 0 + for [l:key, l:value] in items(s:diagnostics_state) + if has_key(l:value, l:server) + let l:notify = 1 + call remove(l:value, l:server) + endif + endfor + if l:notify | call s:notify_diagnostics_update(l:server) | endif +endfunction + +function! lsp#internal#diagnostics#state#_force_notify_buffer(buffer) abort + " TODO: optimize buffer only + call s:notify_diagnostics_update() +endfunction + +" call s:notify_diagnostics_update() +" call s:notify_diagnostics_update('server') +" call s:notify_diagnostics_update('server', 'uri') +function! s:notify_diagnostics_update(...) abort + let l:data = { 'server': '$vimlsp', 'response': { 'method': '$/vimlsp/lsp_diagnostics_updated', 'params': {} } } + " if a:0 > 0 | let l:data['response']['params']['server'] = a:1 | endif + " if a:0 > 1 | let l:data['response']['params']['uri'] = a:2 | endif + call lsp#stream(1, l:data) + doautocmd User lsp_diagnostics_updated +endfunction + +function! lsp#internal#diagnostics#state#_enable_for_buffer(bufnr) abort + if getbufvar(a:bufnr, 'lsp_diagnostics_enabled', 1) == 0 + call setbufvar(a:bufnr, 'lsp_diagnostics_enabled', 1) + call s:notify_diagnostics_update() + endif +endfunction + +function! lsp#internal#diagnostics#state#_disable_for_buffer(bufnr) abort + if getbufvar(a:bufnr, 'lsp_diagnostics_enabled', 1) != 0 + call setbufvar(a:bufnr, 'lsp_diagnostics_enabled', 0) + call s:notify_diagnostics_update() + endif +endfunction + +function! lsp#internal#diagnostics#state#_is_enabled_for_buffer(bufnr) abort + return getbufvar(a:bufnr, 'lsp_diagnostics_enabled', 1) == 1 +endfunction + +" Return dict with diagnostic counts for the specified buffer +" { 'error': 1, 'warning': 0, 'information': 0, 'hint': 0 } +function! lsp#internal#diagnostics#state#_get_diagnostics_count_for_buffer(bufnr) abort + let l:counts = { + \ 'error': 0, + \ 'warning': 0, + \ 'information': 0, + \ 'hint': 0, + \ } + if lsp#internal#diagnostics#state#_is_enabled_for_buffer(a:bufnr) + let l:uri = lsp#utils#get_buffer_uri(a:bufnr) + for [l:_, l:response] in items(lsp#internal#diagnostics#state#_get_all_diagnostics_grouped_by_server_for_uri(l:uri)) + for l:diagnostic in lsp#utils#iteratable(l:response['params']['diagnostics']) + let l:key = get(s:diagnostic_kinds, get(l:diagnostic, 'severity', 1) , 'error') + let l:counts[l:key] += 1 + endfor + endfor + end + return l:counts +endfunction