Files
vim-lsp-mirror/autoload/lsp/ui/vim/signature_help.vim
Fujiwara Takuya 52539a54ae Show diagnostics in a floating window (#700)
* fix comment

* fix indent

* support diagnostics in a floating window

* doc: add g:lsp_diagnostics_float_{cursor,delay}

* fix vint errors except unused variables

* suppress vint unused variable errors

* lint: use robust operator
2020-02-10 01:44:05 +09:00

153 lines
5.1 KiB
VimL

" vint: -ProhibitUnusedVariable
let s:debounce_timer_id = 0
function! s:not_supported(what) abort
return lsp#utils#error(a:what.' not supported for '.&filetype)
endfunction
function! lsp#ui#vim#signature_help#get_signature_help_under_cursor() abort
let l:servers = filter(lsp#get_whitelisted_servers(), 'lsp#capabilities#has_signature_help_provider(v:val)')
if len(l:servers) == 0
call s:not_supported('Retrieving signature help')
return
endif
let l:position = lsp#get_position()
for l:server in l:servers
call lsp#send_request(l:server, {
\ 'method': 'textDocument/signatureHelp',
\ 'params': {
\ 'textDocument': lsp#get_text_document_identifier(),
\ 'position': l:position,
\ },
\ 'on_notification': function('s:handle_signature_help', [l:server]),
\ })
endfor
call lsp#log('Retrieving signature help')
return
endfunction
function! s:handle_signature_help(server, data) abort
if lsp#client#is_error(a:data['response'])
call lsp#utils#error('Failed to retrieve signature help information for ' . a:server)
return
endif
if !has_key(a:data['response'], 'result')
return
endif
if !empty(a:data['response']['result']) && !empty(a:data['response']['result']['signatures'])
" Get current signature.
let l:signatures = get(a:data['response']['result'], 'signatures', [])
let l:signature_index = get(a:data['response']['result'], 'activeSignature', 0)
let l:signature = get(l:signatures, l:signature_index, {})
if empty(l:signature)
return
endif
" Signature label.
let l:label = l:signature['label']
" Mark current parameter.
if has_key(a:data['response']['result'], 'activeParameter')
let l:parameters = get(l:signature, 'parameters', [])
let l:parameter_index = a:data['response']['result']['activeParameter']
let l:parameter = get(l:parameters, l:parameter_index, {})
let l:parameter_label = s:get_parameter_label(l:signature, l:parameter)
if !empty(l:parameter_label)
let l:label = substitute(l:label, '\V\(' . escape(l:parameter_label, '\/?') . '\)', '`\1`', 'g')
endif
endif
let l:contents = [l:label]
if exists('l:parameter')
let l:parameter_doc = s:get_parameter_doc(l:parameter)
if !empty(l:parameter_doc)
call add(l:contents, '')
call add(l:contents, l:parameter_doc)
call add(l:contents, '')
endif
endif
if has_key(l:signature, 'documentation')
call add(l:contents, l:signature['documentation'])
endif
call lsp#ui#vim#output#preview(a:server, l:contents, {'statusline': ' LSP SignatureHelp'})
return
else
" signature help is used while inserting. So this must be graceful.
"call lsp#utils#error('No signature help information found')
endif
endfunction
function! s:get_parameter_label(signature, parameter) abort
if has_key(a:parameter, 'label')
if type(a:parameter['label']) == type([])
let l:string_range = a:parameter['label']
return strcharpart(
\ a:signature['label'],
\ l:string_range[0],
\ l:string_range[1] - l:string_range[0])
endif
return a:parameter['label']
endif
return ''
endfunction
function! s:get_parameter_doc(parameter) abort
if !has_key(a:parameter, 'documentation')
return ''
endif
let l:doc = copy(a:parameter['documentation'])
if type(l:doc) == type({})
let l:doc['value'] = printf('***%s*** - %s', a:parameter['label'], l:doc['value'])
return l:doc
endif
return printf('***%s*** - %s', a:parameter['label'], l:doc)
endfunction
function! s:on_cursor_moved() abort
let l:bufnr = bufnr('%')
call timer_stop(s:debounce_timer_id)
let s:debounce_timer_id = timer_start(500, function('s:on_text_changed_after', [l:bufnr]), { 'repeat': 1 })
endfunction
function! s:on_text_changed_after(bufnr, timer) abort
if bufnr('%') != a:bufnr
return
endif
if index(['i', 's'], mode()[0]) == -1
return
endif
if win_id2win(lsp#ui#vim#output#getpreviewwinid()) >= 1
return
endif
" Cache trigger chars since this loop is heavy
let l:chars = get(b:, 'lsp_signature_help_trigger_character', [])
if empty(l:chars)
for l:server_name in lsp#get_whitelisted_servers(a:bufnr)
let l:chars += lsp#capabilities#get_signature_help_trigger_characters(l:server_name)
endfor
let b:lsp_signature_help_trigger_character = l:chars
endif
if index(l:chars, lsp#utils#_get_before_char_skip_white()) >= 0
call lsp#ui#vim#signature_help#get_signature_help_under_cursor()
endif
endfunction
function! lsp#ui#vim#signature_help#setup() abort
augroup _lsp_signature_help_
autocmd!
autocmd CursorMoved,CursorMovedI * call s:on_cursor_moved()
augroup END
endfunction