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
This commit is contained in:
Bryan Garber 2024-05-01 07:58:06 -03:00 committed by GitHub
parent d19b238aa2
commit 70eeae54fb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 110 additions and 27 deletions

View File

@ -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
let l:item_list = []
call ale#definition#UpdateTagStack()
call ale#util#Open(l:filename, l:line, l:column, l:options)
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

View File

@ -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