diff options
Diffstat (limited to 'autoload')
-rw-r--r-- | autoload/ale/lsp/message.vim | 10 | ||||
-rw-r--r-- | autoload/ale/lsp/tsserver_message.vim | 8 | ||||
-rw-r--r-- | autoload/ale/references.vim | 111 |
3 files changed, 129 insertions, 0 deletions
diff --git a/autoload/ale/lsp/message.vim b/autoload/ale/lsp/message.vim index 0b73cfc2..037e6ce2 100644 --- a/autoload/ale/lsp/message.vim +++ b/autoload/ale/lsp/message.vim @@ -116,3 +116,13 @@ function! ale#lsp#message#Definition(buffer, line, column) abort \ 'position': {'line': a:line - 1, 'character': a:column}, \}] endfunction + +function! ale#lsp#message#References(buffer, line, column) abort + return [0, 'textDocument/references', { + \ 'textDocument': { + \ 'uri': ale#path#ToURI(expand('#' . a:buffer . ':p')), + \ }, + \ 'position': {'line': a:line - 1, 'character': a:column}, + \ 'context': {'includeDeclaration': v:false}, + \}] +endfunction diff --git a/autoload/ale/lsp/tsserver_message.vim b/autoload/ale/lsp/tsserver_message.vim index b9bd7a01..415fde95 100644 --- a/autoload/ale/lsp/tsserver_message.vim +++ b/autoload/ale/lsp/tsserver_message.vim @@ -61,3 +61,11 @@ function! ale#lsp#tsserver_message#Definition(buffer, line, column) abort \ 'file': expand('#' . a:buffer . ':p'), \}] endfunction + +function! ale#lsp#tsserver_message#References(buffer, line, column) abort + return [0, 'ts@references', { + \ 'line': a:line, + \ 'offset': a:column, + \ 'file': expand('#' . a:buffer . ':p'), + \}] +endfunction diff --git a/autoload/ale/references.vim b/autoload/ale/references.vim new file mode 100644 index 00000000..9777519d --- /dev/null +++ b/autoload/ale/references.vim @@ -0,0 +1,111 @@ +let s:references_map = {} + +" Used to get the references map in tests. +function! ale#references#GetMap() abort + return deepcopy(s:references_map) +endfunction + +" Used to set the references map in tests. +function! ale#references#SetMap(map) abort + let s:references_map = a:map +endfunction + +function! ale#references#ClearLSPData() abort + let s:references_map = {} +endfunction + +function! ale#references#HandleTSServerResponse(conn_id, response) abort + if get(a:response, 'command', '') is# 'references' + \&& has_key(s:references_map, a:response.request_seq) + call remove(s:references_map, a:response.request_seq) + + if get(a:response, 'success', v:false) is v:true + let l:item_list = [] + + for l:response_item in a:response.body.refs + call add(l:item_list, { + \ 'filename': l:response_item.file, + \ 'line': l:response_item.start.line, + \ 'column': l:response_item.start.offset, + \}) + endfor + + if empty(l:item_list) + call ale#util#Execute('echom ''No references found.''') + else + call ale#preview#ShowSelection(l:item_list) + endif + endif + endif +endfunction + +function! ale#references#HandleLSPResponse(conn_id, response) abort + if has_key(a:response, 'id') + \&& has_key(s:references_map, a:response.id) + call remove(s:references_map, a:response.id) + + " The result can be a Dictionary item, a List of the same, or null. + let l:result = get(a:response, 'result', []) + let l:item_list = [] + + for l:response_item in l:result + call add(l:item_list, { + \ 'filename': ale#path#FromURI(l:response_item.uri), + \ 'line': l:response_item.range.start.line + 1, + \ 'column': l:response_item.range.start.character + 1, + \}) + endfor + + if empty(l:item_list) + call ale#util#Execute('echom ''No references found.''') + else + call ale#preview#ShowSelection(l:item_list) + endif + endif +endfunction + +function! s:FindReferences(linter) abort + let l:buffer = bufnr('') + let [l:line, l:column] = getcurpos()[1:2] + + let l:Callback = a:linter.lsp is# 'tsserver' + \ ? function('ale#references#HandleTSServerResponse') + \ : function('ale#references#HandleLSPResponse') + + let l:lsp_details = ale#linter#StartLSP(l:buffer, a:linter, l:Callback) + + if empty(l:lsp_details) + return 0 + endif + + let l:id = l:lsp_details.connection_id + let l:root = l:lsp_details.project_root + + if a:linter.lsp is# 'tsserver' + let l:message = ale#lsp#tsserver_message#References( + \ l:buffer, + \ l:line, + \ l:column + \) + else + " Send a message saying the buffer has changed first, or the + " references position probably won't make sense. + call ale#lsp#Send(l:id, ale#lsp#message#DidChange(l:buffer), l:root) + + let l:column = min([l:column, len(getline(l:line))]) + + let l:message = ale#lsp#message#References(l:buffer, l:line, l:column) + endif + + let l:request_id = ale#lsp#Send(l:id, l:message, l:root) + + let s:references_map[l:request_id] = {} +endfunction + +function! ale#references#Find() abort + for l:linter in ale#linter#Get(&filetype) + if !empty(l:linter.lsp) + call s:FindReferences(l:linter) + endif + endfor +endfunction |