Skip to content

Commit 67caa41

Browse files
authoredJan 1, 2020
add initial support for type hierarchy (#641)
1 parent 2afe76d commit 67caa41

File tree

8 files changed

+407
-1
lines changed

8 files changed

+407
-1
lines changed
 

‎LICENSE-THIRD-PARTY

+12
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,15 @@ their own copyright notices and license terms:
3333
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3434
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3535

36+
37+
* vim-yggdrasil - https://github.com/m-pilia/vim-yggdrasil
38+
* autoload/utils/tree.vim
39+
====================================================================
40+
41+
Copyright 2019 Martino Pilia <martino.pilia@gmail.com>
42+
43+
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:
44+
45+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
46+
47+
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.

‎README.md

+1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ Refer to `:h vim-lsp-semantic` for more info.
115115
|`:LspRename`| Rename symbol |
116116
|`:LspStatus` | Show the status of the language server |
117117
|`:LspTypeDefinition`| Go to the type definition of the word under the cursor, and open in the current window |
118+
|`:LspTypeHierarchy`| View type hierarchy of the symbol under the cursor |
118119
|`:LspWorkspaceSymbol`| Search/Show workspace symbol |
119120

120121
### Diagnostics

‎autoload/lsp.vim

+2-1
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,8 @@ function! lsp#default_get_supported_capabilities(server_info) abort
451451
\ },
452452
\ 'semanticHighlightingCapabilities': {
453453
\ 'semanticHighlighting': lsp#ui#vim#semantic#is_enabled()
454-
\ }
454+
\ },
455+
\ 'typeHierarchy': v:false,
455456
\ }
456457
\ }
457458
endfunction

‎autoload/lsp/capabilities.vim

+4
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ function! lsp#capabilities#has_type_definition_provider(server_name) abort
6969
return s:has_bool_provider(a:server_name, 'typeDefinitionProvider')
7070
endfunction
7171

72+
function! lsp#capabilities#has_type_hierarchy_provider(server_name) abort
73+
return s:has_bool_provider(a:server_name, 'typeHierarchyProvider')
74+
endfunction
75+
7276
function! lsp#capabilities#has_document_highlight_provider(server_name) abort
7377
return s:has_bool_provider(a:server_name, 'documentHighlightProvider')
7478
endfunction

‎autoload/lsp/ui/vim.vim

+104
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,32 @@ function! lsp#ui#vim#type_definition(in_preview) abort
5252
echo 'Retrieving type definition ...'
5353
endfunction
5454

55+
function! lsp#ui#vim#type_hierarchy() abort
56+
let l:servers = filter(lsp#get_whitelisted_servers(), 'lsp#capabilities#has_type_hierarchy_provider(v:val)')
57+
let s:last_req_id = s:last_req_id + 1
58+
59+
if len(l:servers) == 0
60+
call s:not_supported('Retrieving type hierarchy')
61+
return
62+
endif
63+
let l:ctx = { 'counter': len(l:servers), 'list':[], 'last_req_id': s:last_req_id }
64+
" direction 0 children, 1 parent, 2 both
65+
for l:server in l:servers
66+
call lsp#send_request(l:server, {
67+
\ 'method': 'textDocument/typeHierarchy',
68+
\ 'params': {
69+
\ 'textDocument': lsp#get_text_document_identifier(),
70+
\ 'position': lsp#get_position(),
71+
\ 'direction': 2,
72+
\ 'resolve': 1,
73+
\ },
74+
\ 'on_notification': function('s:handle_type_hierarchy', [l:ctx, l:server, 'type hierarchy']),
75+
\ })
76+
endfor
77+
78+
echo 'Retrieving type hierarchy ...'
79+
endfunction
80+
5581
function! lsp#ui#vim#declaration(in_preview) abort
5682
let l:servers = filter(lsp#get_whitelisted_servers(), 'lsp#capabilities#has_declaration_provider(v:val)')
5783
let s:last_req_id = s:last_req_id + 1
@@ -630,6 +656,84 @@ function! s:handle_code_action(server, last_req_id, type, data) abort
630656
endif
631657
endfunction
632658

659+
function! s:handle_type_hierarchy(ctx, server, type, data) abort "ctx = {counter, list, last_req_id}
660+
if a:ctx['last_req_id'] != s:last_req_id
661+
return
662+
endif
663+
664+
if lsp#client#is_error(a:data['response'])
665+
call lsp#utils#error('Failed to '. a:type . ' for ' . a:server . ': ' . lsp#client#error_message(a:data['response']))
666+
return
667+
endif
668+
669+
if empty(a:data['response']['result'])
670+
echo 'No type hierarchy found'
671+
return
672+
endif
673+
674+
" Create new buffer in a split
675+
let l:position = 'topleft'
676+
let l:orientation = 'new'
677+
exec l:position . ' ' . 10 . l:orientation
678+
679+
let l:provider = {
680+
\ 'root': a:data['response']['result'],
681+
\ 'root_state': 'expanded',
682+
\ 'bufnr': bufnr('%'),
683+
\ 'getChildren': function('s:get_children_for_tree_hierarchy'),
684+
\ 'getParent': function('s:get_parent_for_tree_hierarchy'),
685+
\ 'getTreeItem': function('s:get_treeitem_for_tree_hierarchy'),
686+
\ }
687+
688+
call lsp#utils#tree#new(l:provider)
689+
690+
echo 'Retrieved type hierarchy'
691+
endfunction
692+
693+
function! s:hierarchyitem_to_treeitem(hierarchyitem) abort
694+
return {
695+
\ 'id': a:hierarchyitem,
696+
\ 'label': a:hierarchyitem['name'],
697+
\ 'command': function('s:hierarchy_treeitem_command', [a:hierarchyitem]),
698+
\ 'collapsibleState': has_key(a:hierarchyitem, 'parents') && !empty(a:hierarchyitem['parents']) ? 'expanded' : 'none',
699+
\ }
700+
endfunction
701+
702+
function! s:hierarchy_treeitem_command(hierarchyitem) abort
703+
bwipeout
704+
705+
let l:path = lsp#utils#uri_to_path(a:hierarchyitem['uri'])
706+
let l:line = a:hierarchyitem['range']['start']['line'] + 1
707+
let l:char = a:hierarchyitem['range']['start']['character']
708+
let l:col = lsp#utils#to_col(l:path, l:line, l:char)
709+
710+
let l:buffer = bufnr(l:path)
711+
if &modified && !&hidden
712+
let l:cmd = l:buffer !=# -1 ? 'sb ' . l:buffer : 'split ' . fnameescape(l:path)
713+
else
714+
echom 'edit'
715+
let l:cmd = l:buffer !=# -1 ? 'b ' . l:buffer : 'edit ' . fnameescape(l:path)
716+
endif
717+
execute l:cmd . ' | call cursor('.l:line.','.l:col.')'
718+
endfunction
719+
720+
function! s:get_children_for_tree_hierarchy(Callback, ...) dict abort
721+
if a:0 == 0
722+
call a:Callback('success', [l:self['root']])
723+
return
724+
else
725+
call a:Callback('success', a:1['parents'])
726+
endif
727+
endfunction
728+
729+
function! s:get_parent_for_tree_hierarchy(...) dict abort
730+
" TODO
731+
endfunction
732+
733+
function! s:get_treeitem_for_tree_hierarchy(Callback, object) dict abort
734+
call a:Callback('success', s:hierarchyitem_to_treeitem(a:object))
735+
endfunction
736+
633737
" @params
634738
" server - string
635739
" comand_or_code_action - Command | CodeAction

0 commit comments

Comments
 (0)