add support for call hierarchy (#1046)

* add support for call hierarchy

* no need to use a timer

https://github.com/prabirshrestha/vim-lsp/pull/1046#discussion_r559003701

* add commands to README.md
This commit is contained in:
Daisuke Suzuki
2021-01-18 11:44:25 +09:00
committed by GitHub
parent 951ed0ca0f
commit 17180038a8
5 changed files with 109 additions and 0 deletions

View File

@@ -105,6 +105,8 @@ Refer to `:h vim-lsp-semantic` for more info.
| Command | Description|
|--|--|
|`:LspCallHierarchyIncoming`| Find incoming call hierarchy for the symbol under cursor |
|`:LspCallHierarchyOutgoing`| Find outgoing call hierarchy for the symbol under cursor |
|`:LspCodeAction`| Gets a list of possible commands that can be applied to a file so it can be fixed (quick fix) |
|`:LspCodeLens`| Gets a list of possible commands that can be executed on the current document |
|`:LspDeclaration`| Go to the declaration of the word under the cursor, and open in the current window |

View File

@@ -89,6 +89,10 @@ function! lsp#capabilities#has_folding_range_provider(server_name) abort
return s:has_provider(a:server_name, 'foldingRangeProvider')
endfunction
function! lsp#capabilities#has_call_hierarchy_provider(server_name) abort
return s:has_provider(a:server_name, 'callHierarchyProvider')
endfunction
function! lsp#capabilities#has_semantic_highlight(server_name) abort
let l:capabilities = lsp#get_server_capabilities(a:server_name)

View File

@@ -344,3 +344,90 @@ function! lsp#ui#vim#code_lens() abort
\ 'sync': v:false,
\ })
endfunction
function! lsp#ui#vim#call_hierarchy_incoming() abort
let l:ctx = { 'method': 'incomingCalls', 'key': 'from' }
call s:prepare_call_hierarchy(l:ctx)
endfunction
function! lsp#ui#vim#call_hierarchy_outgoing() abort
let l:ctx = { 'method': 'outgoingCalls', 'key': 'to' }
call s:prepare_call_hierarchy(l:ctx)
endfunction
function! s:prepare_call_hierarchy(ctx) abort
let l:servers = filter(lsp#get_allowed_servers(), 'lsp#capabilities#has_call_hierarchy_provider(v:val)')
let l:command_id = lsp#_new_command()
let l:ctx = extend({ 'counter': len(l:servers), 'list':[], 'last_command_id': l:command_id }, a:ctx)
if len(l:servers) == 0
call s:not_supported('Retrieving call hierarchy')
return
endif
for l:server in l:servers
call lsp#send_request(l:server, {
\ 'method': 'textDocument/prepareCallHierarchy',
\ 'params': {
\ 'textDocument': lsp#get_text_document_identifier(),
\ 'position': lsp#get_position(),
\ },
\ 'on_notification': function('s:handle_prepare_call_hierarchy', [l:ctx, l:server, 'prepare_call_hierarchy']),
\ })
endfor
echo 'Preparing call hierarchy ...'
endfunction
function! s:handle_prepare_call_hierarchy(ctx, server, type, data) abort
if a:ctx['last_command_id'] != lsp#_last_command()
return
endif
if lsp#client#is_error(a:data['response']) || !has_key(a:data['response'], 'result')
call lsp#utils#error('Failed to '. a:type . ' for ' . a:server . ': ' . lsp#client#error_message(a:data['response']))
return
endif
for l:item in a:data['response']['result']
call s:call_hierarchy(a:ctx, a:server, l:item)
endfor
endfunction
function! s:call_hierarchy(ctx, server, item) abort
call lsp#send_request(a:server, {
\ 'method': 'callHierarchy/' . a:ctx['method'],
\ 'params': {
\ 'item': a:item,
\ },
\ 'on_notification': function('s:handle_call_hierarchy', [a:ctx, a:server, 'call_hierarchy']),
\ })
endfunction
function! s:handle_call_hierarchy(ctx, server, type, data) abort
if a:ctx['last_command_id'] != lsp#_last_command()
return
endif
let a:ctx['counter'] = a:ctx['counter'] - 1
if lsp#client#is_error(a:data['response']) || !has_key(a:data['response'], 'result')
call lsp#utils#error('Failed to retrieve '. a:type . ' for ' . a:server . ': ' . lsp#client#error_message(a:data['response']))
else
for l:item in a:data['response']['result']
let a:ctx['list'] = a:ctx['list'] + lsp#utils#location#_lsp_to_vim_list(l:item[a:ctx['key']])
endfor
endif
if a:ctx['counter'] == 0
if empty(a:ctx['list'])
call lsp#utils#error('No ' . a:type .' found')
else
call lsp#utils#tagstack#_update()
call setqflist([])
call setqflist(a:ctx['list'])
echo 'Retrieved ' . a:type
botright copen
endif
endif
endfunction

View File

@@ -85,6 +85,8 @@ CONTENTS *vim-lsp-contents*
lsp#get_buffer_first_error_line() |lsp#get_buffer_first_error_line()|
lsp#get_progress() |lsp#get_progress()|
Commands |vim-lsp-commands|
LspCallHierarchyIncoming |:LspCallHierarchyIncoming|
LspCallHierarchyOutgoing |:LspCallHierarchyOutgoing|
LspCodeAction |:LspCodeAction|
LspCodeActionSync |:LspCodeActionSync|
LspCodeLens |:LspCodeLens|
@@ -1332,6 +1334,14 @@ lsp#get_progress() *lsp#get_progress()*
==============================================================================
Commands *vim-lsp-commands*
LspCallHierarchyIncoming *:LspCallHierarchyIncoming*
Find incoming call hierarchy for the symbol under cursor.
LspCallHierarchyOutgoing *:LspCallHierarchyOutgoing*
Find outgoing call hierarchy for the symbol under cursor.
LspCodeAction [{CodeActionKind}] *:LspCodeAction*
Gets a list of possible commands that can be applied to a file so it can be
@@ -1633,6 +1643,8 @@ To map keys to the feature of vim-lsp, use <plug> mappings:
<
Available plug mappings are following:
nnoremap <plug>(lsp-call-hierarchy-incoming)
nnoremap <plug>(lsp-call-hierarchy-outgoing)
nnoremap <plug>(lsp-code-action)
nnoremap <plug>(lsp-code-lens)
nnoremap <plug>(lsp-declaration)

View File

@@ -72,6 +72,8 @@ if g:lsp_auto_enable
augroup END
endif
command! LspCallHierarchyIncoming call lsp#ui#vim#call_hierarchy_incoming()
command! LspCallHierarchyOutgoing call lsp#ui#vim#call_hierarchy_outgoing()
command! -range -nargs=* -complete=customlist,lsp#ui#vim#code_action#complete LspCodeAction call lsp#ui#vim#code_action#do({
\ 'sync': v:false,
\ 'selection': <range> != 0,
@@ -130,6 +132,8 @@ command! LspDocumentFold call lsp#ui#vim#folding#fold(0)
command! LspDocumentFoldSync call lsp#ui#vim#folding#fold(1)
command! -nargs=? LspSemanticScopes call lsp#ui#vim#semantic#display_scope_tree(<args>)
nnoremap <plug>(lsp-call-hierarchy-incoming) :<c-u>call lsp#ui#vim#call_hierarchy_incoming()<cr>
nnoremap <plug>(lsp-call-hierarchy-outgoing) :<c-u>call lsp#ui#vim#call_hierarchy_outgoing()<cr>
nnoremap <plug>(lsp-code-action) :<c-u>call lsp#ui#vim#code_action()<cr>
nnoremap <plug>(lsp-code-lens) :<c-u>call lsp#ui#vim#code_lens()<cr>
nnoremap <plug>(lsp-declaration) :<c-u>call lsp#ui#vim#declaration(0)<cr>