diff options
author | Bryan Garber <spellcasterbryan@gmail.com> | 2024-05-01 07:58:06 -0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-01 11:58:06 +0100 |
commit | 70eeae54fbd5c2e254604d543674f02d42c0ccdd (patch) | |
tree | 3be622cad5c33da7bf10eb1880af7073a359ccea | |
parent | d19b238aa2d7c426e71c5de083bd61328d5c4fd4 (diff) | |
download | ale-70eeae54fbd5c2e254604d543674f02d42c0ccdd.zip |
Implement listing all returned results for LSP textDocument/implements (#4755)
* Fix list of definitions
* Fix when LSP returns single response on definition/implementation
* Update tag stack on ShowSelection
-rw-r--r-- | autoload/ale/definition.vim | 129 | ||||
-rw-r--r-- | test/test_go_to_definition.vader | 10 |
2 files changed, 111 insertions, 28 deletions
diff --git a/autoload/ale/definition.vim b/autoload/ale/definition.vim index 251bdcc5..210ee038 100644 --- a/autoload/ale/definition.vim +++ b/autoload/ale/definition.vim @@ -35,22 +35,94 @@ function! ale#definition#UpdateTagStack() abort endif endfunction +function! ale#definition#FormatTSServerResponse(response_item, options) abort + if get(a:options, 'open_in') is# 'quickfix' + return { + \ 'filename': a:response_item.file, + \ 'lnum': a:response_item.start.line, + \ 'col': a:response_item.start.offset, + \} + else + return { + \ 'filename': a:response_item.file, + \ 'line': a:response_item.start.line, + \ 'column': a:response_item.start.offset, + \} + endif +endfunction + function! ale#definition#HandleTSServerResponse(conn_id, response) abort if has_key(a:response, 'request_seq') \&& has_key(s:go_to_definition_map, a:response.request_seq) let l:options = remove(s:go_to_definition_map, a:response.request_seq) if get(a:response, 'success', v:false) is v:true && !empty(a:response.body) - let l:filename = a:response.body[0].file - let l:line = a:response.body[0].start.line - let l:column = a:response.body[0].start.offset - - call ale#definition#UpdateTagStack() - call ale#util#Open(l:filename, l:line, l:column, l:options) + let l:item_list = [] + + for l:response_item in a:response.body + call add( + \ l:item_list, + \ ale#definition#FormatTSServerResponse(l:response_item, l:options) + \) + endfor + + if empty(l:item_list) + call ale#util#Execute('echom ''No definitions found''') + elseif len(l:item_list) == 1 + let l:filename = l:item_list[0].filename + + if get(l:options, 'open_in') is# 'quickfix' + let l:line = l:item_list[0].lnum + let l:column = l:item_list[0].col + else + let l:line = l:item_list[0].line + let l:column = l:item_list[0].column + endif + + call ale#definition#UpdateTagStack() + call ale#util#Open(l:filename, l:line, l:column, l:options) + else + if get(l:options, 'open_in') is# 'quickfix' + call setqflist([], 'r') + call setqflist(l:item_list, 'a') + call ale#util#Execute('cc 1') + else + call ale#definition#UpdateTagStack() + call ale#preview#ShowSelection(l:item_list, l:options) + endif + endif endif endif endfunction +function! ale#definition#FormatLSPResponse(response_item, options) abort + if has_key(a:response_item, 'targetUri') + " LocationLink items use targetUri + let l:uri = a:response_item.targetUri + let l:line = a:response_item.targetRange.start.line + 1 + let l:column = a:response_item.targetRange.start.character + 1 + else + " LocationLink items use uri + let l:uri = a:response_item.uri + let l:line = a:response_item.range.start.line + 1 + let l:column = a:response_item.range.start.character + 1 + endif + + if get(a:options, 'open_in') is# 'quickfix' + return { + \ 'filename': ale#util#ToResource(l:uri), + \ 'lnum': l:line, + \ 'col': l:column, + \} + else + return { + \ 'filename': ale#util#ToResource(l:uri), + \ 'line': l:line, + \ 'column': l:column, + \} + endif +endfunction + function! ale#definition#HandleLSPResponse(conn_id, response) abort if has_key(a:response, 'id') \&& has_key(s:go_to_definition_map, a:response.id) @@ -65,21 +137,29 @@ function! ale#definition#HandleLSPResponse(conn_id, response) abort let l:result = [] endif - for l:item in l:result - if has_key(l:item, 'targetUri') - " LocationLink items use targetUri - let l:uri = l:item.targetUri - let l:line = l:item.targetRange.start.line + 1 - let l:column = l:item.targetRange.start.character + 1 - else - " LocationLink items use uri - let l:uri = l:item.uri - let l:line = l:item.range.start.line + 1 - let l:column = l:item.range.start.character + 1 - endif + let l:item_list = [] + + for l:response_item in l:result + call add(l:item_list, + \ ale#definition#FormatLSPResponse(l:response_item, l:options) + \) + endfor + if empty(l:item_list) + call ale#util#Execute('echom ''No definitions found''') + elseif len(l:item_list) == 1 call ale#definition#UpdateTagStack() + let l:uri = ale#util#ToURI(l:item_list[0].filename) + + if get(l:options, 'open_in') is# 'quickfix' + let l:line = l:item_list[0].lnum + let l:column = l:item_list[0].col + else + let l:line = l:item_list[0].line + let l:column = l:item_list[0].column + endif + let l:uri_handler = ale#uri#GetURIHandler(l:uri) if l:uri_handler is# v:null @@ -88,9 +168,16 @@ function! ale#definition#HandleLSPResponse(conn_id, response) abort else call l:uri_handler.OpenURILink(l:uri, l:line, l:column, l:options, a:conn_id) endif - - break - endfor + else + if get(l:options, 'open_in') is# 'quickfix' + call setqflist([], 'r') + call setqflist(l:item_list, 'a') + call ale#util#Execute('cc 1') + else + call ale#definition#UpdateTagStack() + call ale#preview#ShowSelection(l:item_list, l:options) + endif + endif endif endfunction diff --git a/test/test_go_to_definition.vader b/test/test_go_to_definition.vader index 726de551..2290054a 100644 --- a/test/test_go_to_definition.vader +++ b/test/test_go_to_definition.vader @@ -458,19 +458,15 @@ Execute(Definition responses with lists should be handled): \ } \) - AssertEqual - \ [ - \ 'edit +3 ' . fnameescape(ale#path#Simplify(g:dir . '/completion_dummy_file')), - \ ], - \ g:expr_list - AssertEqual [3, 8], getpos('.')[1:2] + " Multiple results should either open the ALEPreview or go to quickfix + AssertEqual [1, 1], getpos('.')[1:2] AssertEqual {}, ale#definition#GetMap() Execute(Definition responses with null response should be handled): call ale#definition#SetMap({3: {'open_in': 'current-buffer'}}) call ale#definition#HandleLSPResponse(1, {'id': 3, 'result': v:null}) - AssertEqual [], g:expr_list + AssertEqual ['echom ''No definitions found'''], g:expr_list Execute(LSP definition requests should be sent): runtime ale_linters/python/pylsp.vim |