Add API for custom LSP requests

Implement a function `ale#lsp_linter#SendRequest` that allows to send
custom LSP requests to an enabled LSP linter.

Resolves #2474
This commit is contained in:
Martino Pilia
2019-05-31 17:26:53 +02:00
parent 27146ade32
commit 7053d468cc
4 changed files with 192 additions and 4 deletions

View File

@@ -5,6 +5,9 @@
let s:connections = get(s:, 'connections', {})
let g:ale_lsp_next_message_id = 1
" A Dictionary to track one-shot callbacks for custom LSP requests
let s:custom_callbacks = get(s:, 'custom_callbacks', {})
" Given an id, which can be an executable or address, and a project path,
" create a new connection if needed. Return a unique ID for the connection.
function! ale#lsp#Register(executable_or_address, project, init_options) abort
@@ -296,10 +299,19 @@ function! ale#lsp#HandleMessage(conn_id, message) abort
" responses.
if l:conn.initialized
for l:response in l:response_list
" Call all of the registered handlers with the response.
for l:Callback in l:conn.callback_list
call ale#util#GetFunction(l:Callback)(a:conn_id, l:response)
endfor
if has_key(l:response, 'id') && has_key(s:custom_callbacks, l:response.id)
" Response to a custom request, call the registered one-shot handler.
try
call s:custom_callbacks[l:response.id](l:response)
finally
call remove(s:custom_callbacks, l:response.id)
endtry
else
" Call all of the registered handlers with the response.
for l:Callback in l:conn.callback_list
call ale#util#GetFunction(l:Callback)(a:conn_id, l:response)
endfor
endif
endfor
endif
endfunction
@@ -525,6 +537,18 @@ function! ale#lsp#Send(conn_id, message) abort
return l:id == 0 ? -1 : l:id
endfunction
" Send a custom request to an LSP server.
" The given callback is called on response.
function! ale#lsp#SendCustomRequest(conn_id, message, Callback) abort
let l:id = ale#lsp#Send(a:conn_id, a:message)
if l:id > 0
let s:custom_callbacks[l:id] = a:Callback
endif
return l:id
endfunction
" Notify LSP servers or tsserver if a document is opened, if needed.
" If a document is opened, 1 will be returned, otherwise 0 will be returned.
function! ale#lsp#OpenDocument(conn_id, buffer, language_id) abort

View File

@@ -413,3 +413,29 @@ endfunction
function! ale#lsp_linter#SetLSPLinterMap(replacement_map) abort
let s:lsp_linter_map = a:replacement_map
endfunction
" Send a custom request to an LSP linter.
function! ale#lsp_linter#SendRequest(buffer, linter_name, method, parameters, Callback) abort
let l:filetype = ale#linter#ResolveFiletype(getbufvar(a:buffer, '&filetype'))
let l:linter_list = ale#linter#GetAll(l:filetype)
let l:linter_list = filter(l:linter_list, {_, v -> v.name is# a:linter_name})
if len(l:linter_list) < 1
throw 'Linter "' . a:linter_name . '" not found!'
endif
let l:linter = l:linter_list[0]
let l:executable_or_address = ''
if l:linter.lsp is# 'socket'
let l:executable_or_address = ale#linter#GetAddress(a:buffer, l:linter)
else
let l:executable_or_address = ale#linter#GetExecutable(a:buffer, l:linter)
endif
let l:root = ale#util#GetFunction(l:linter.project_root)(a:buffer)
let l:conn_id = l:executable_or_address . ':' . l:root
let l:message = [0, a:method, a:parameters]
return ale#lsp#SendCustomRequest(l:conn_id, l:message, a:Callback) == 0
endfunction