Refactor LSP jobs to use a uniform ID value
This commit is contained in:
parent
9f21e45156
commit
5b731f761f
@ -6,9 +6,9 @@ let s:delay = 300
|
|||||||
let s:max_suggestions = 20
|
let s:max_suggestions = 20
|
||||||
let s:buffer_completion_map = {}
|
let s:buffer_completion_map = {}
|
||||||
|
|
||||||
function! s:RememberCompletionInfo(buffer, executable, request_id, line, column) abort
|
function! s:RememberCompletionInfo(buffer, conn_id, request_id, line, column) abort
|
||||||
let s:buffer_completion_map[a:buffer] = {
|
let s:buffer_completion_map[a:buffer] = {
|
||||||
\ 'executable': a:executable,
|
\ 'conn_id': a:conn_id,
|
||||||
\ 'request_id': a:request_id,
|
\ 'request_id': a:request_id,
|
||||||
\ 'line': a:line,
|
\ 'line': a:line,
|
||||||
\ 'column': a:column,
|
\ 'column': a:column,
|
||||||
@ -48,8 +48,8 @@ function! s:HandleCompletions(response) abort
|
|||||||
call add(l:names, l:suggestion.name)
|
call add(l:names, l:suggestion.name)
|
||||||
endfor
|
endfor
|
||||||
|
|
||||||
let l:request_id = ale#lsp#SendMessageToProgram(
|
let l:request_id = ale#lsp#Send(
|
||||||
\ l:info.executable,
|
\ l:info.conn_id,
|
||||||
\ ale#lsp#tsserver_message#CompletionEntryDetails(
|
\ ale#lsp#tsserver_message#CompletionEntryDetails(
|
||||||
\ l:buffer,
|
\ l:buffer,
|
||||||
\ l:info.line,
|
\ l:info.line,
|
||||||
@ -119,40 +119,37 @@ function! s:GetCompletionsForTSServer(buffer, linter, line, column) abort
|
|||||||
let l:executable = has_key(a:linter, 'executable_callback')
|
let l:executable = has_key(a:linter, 'executable_callback')
|
||||||
\ ? ale#util#GetFunction(a:linter.executable_callback)(a:buffer)
|
\ ? ale#util#GetFunction(a:linter.executable_callback)(a:buffer)
|
||||||
\ : a:linter.executable
|
\ : a:linter.executable
|
||||||
let l:command = l:executable
|
let l:command = ale#job#PrepareCommand(l:executable)
|
||||||
|
|
||||||
let l:job_id = ale#lsp#StartProgram(
|
let l:id = ale#lsp#StartProgram(
|
||||||
\ l:executable,
|
|
||||||
\ l:executable,
|
\ l:executable,
|
||||||
|
\ l:command,
|
||||||
\ function('s:HandleLSPResponse')
|
\ function('s:HandleLSPResponse')
|
||||||
\)
|
\)
|
||||||
|
|
||||||
if !l:job_id
|
if !l:id
|
||||||
if g:ale_history_enabled
|
if g:ale_history_enabled
|
||||||
call ale#history#Add(a:buffer, 'failed', l:job_id, l:command)
|
call ale#history#Add(a:buffer, 'failed', l:id, l:command)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if ale#lsp#OpenTSServerDocumentIfNeeded(l:executable, a:buffer)
|
if ale#lsp#OpenTSServerDocumentIfNeeded(l:id, a:buffer)
|
||||||
if g:ale_history_enabled
|
if g:ale_history_enabled
|
||||||
call ale#history#Add(a:buffer, 'started', l:job_id, l:command)
|
call ale#history#Add(a:buffer, 'started', l:id, l:command)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call ale#lsp#SendMessageToProgram(
|
call ale#lsp#Send(l:id, ale#lsp#tsserver_message#Change(a:buffer))
|
||||||
\ l:executable,
|
|
||||||
\ ale#lsp#tsserver_message#Change(a:buffer),
|
|
||||||
\)
|
|
||||||
|
|
||||||
let l:request_id = ale#lsp#SendMessageToProgram(
|
let l:request_id = ale#lsp#Send(
|
||||||
\ l:executable,
|
\ l:id,
|
||||||
\ ale#lsp#tsserver_message#Completions(a:buffer, a:line, a:column),
|
\ ale#lsp#tsserver_message#Completions(a:buffer, a:line, a:column),
|
||||||
\)
|
\)
|
||||||
|
|
||||||
if l:request_id
|
if l:request_id
|
||||||
call s:RememberCompletionInfo(
|
call s:RememberCompletionInfo(
|
||||||
\ a:buffer,
|
\ a:buffer,
|
||||||
\ l:executable,
|
\ l:id,
|
||||||
\ l:request_id,
|
\ l:request_id,
|
||||||
\ a:line,
|
\ a:line,
|
||||||
\ a:column,
|
\ a:column,
|
||||||
|
@ -564,29 +564,30 @@ function! s:CheckWithTSServer(buffer, linter, executable) abort
|
|||||||
let l:info = g:ale_buffer_info[a:buffer]
|
let l:info = g:ale_buffer_info[a:buffer]
|
||||||
|
|
||||||
let l:command = ale#job#PrepareCommand(a:executable)
|
let l:command = ale#job#PrepareCommand(a:executable)
|
||||||
let l:job_id = ale#lsp#StartProgram(a:executable, l:command, function('s:HandleLSPResponse'))
|
let l:id = ale#lsp#StartProgram(
|
||||||
|
\ a:executable,
|
||||||
|
\ l:command,
|
||||||
|
\ function('s:HandleLSPResponse'),
|
||||||
|
\)
|
||||||
|
|
||||||
if !l:job_id
|
if !l:id
|
||||||
if g:ale_history_enabled
|
if g:ale_history_enabled
|
||||||
call ale#history#Add(a:buffer, 'failed', l:job_id, l:command)
|
call ale#history#Add(a:buffer, 'failed', l:id, l:command)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if ale#lsp#OpenTSServerDocumentIfNeeded(a:executable, a:buffer)
|
if ale#lsp#OpenTSServerDocumentIfNeeded(l:id, a:buffer)
|
||||||
if g:ale_history_enabled
|
if g:ale_history_enabled
|
||||||
call ale#history#Add(a:buffer, 'started', l:job_id, l:command)
|
call ale#history#Add(a:buffer, 'started', l:id, l:command)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
call ale#lsp#SendMessageToProgram(
|
call ale#lsp#Send(l:id, ale#lsp#tsserver_message#Change(a:buffer))
|
||||||
\ a:executable,
|
|
||||||
\ ale#lsp#tsserver_message#Change(a:buffer),
|
|
||||||
\)
|
|
||||||
|
|
||||||
let l:request_id = ale#lsp#SendMessageToProgram(
|
let l:request_id = ale#lsp#Send(
|
||||||
\ a:executable,
|
\ l:id,
|
||||||
\ ale#lsp#tsserver_message#Geterr(a:buffer),
|
\ ale#lsp#tsserver_message#Geterr(a:buffer),
|
||||||
\)
|
\)
|
||||||
|
|
||||||
|
@ -7,15 +7,13 @@ let s:connections = []
|
|||||||
let g:ale_lsp_next_message_id = 1
|
let g:ale_lsp_next_message_id = 1
|
||||||
|
|
||||||
function! s:NewConnection() abort
|
function! s:NewConnection() abort
|
||||||
|
" id: The job ID as a Number, or the server address as a string.
|
||||||
" data: The message data received so far.
|
" data: The message data received so far.
|
||||||
" address: An address only set for server connections.
|
|
||||||
" executable: An executable only set for program connections.
|
" executable: An executable only set for program connections.
|
||||||
" job: A job ID only set for running programs.
|
" open_documents: A list of buffers we told the server we opened.
|
||||||
let l:conn = {
|
let l:conn = {
|
||||||
|
\ 'id': '',
|
||||||
\ 'data': '',
|
\ 'data': '',
|
||||||
\ 'address': '',
|
|
||||||
\ 'executable': '',
|
|
||||||
\ 'job_id': -1,
|
|
||||||
\ 'open_documents': [],
|
\ 'open_documents': [],
|
||||||
\}
|
\}
|
||||||
|
|
||||||
@ -24,6 +22,15 @@ function! s:NewConnection() abort
|
|||||||
return l:conn
|
return l:conn
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! s:FindConnection(key, value) abort
|
||||||
|
for l:conn in s:connections
|
||||||
|
if has_key(l:conn, a:key) && get(l:conn, a:key) == a:value
|
||||||
|
return l:conn
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
return {}
|
||||||
|
endfunction
|
||||||
|
|
||||||
function! ale#lsp#GetNextMessageID() abort
|
function! ale#lsp#GetNextMessageID() abort
|
||||||
" Use the current ID
|
" Use the current ID
|
||||||
@ -151,13 +158,13 @@ endfunction
|
|||||||
function! s:HandleChannelMessage(channel, message) abort
|
function! s:HandleChannelMessage(channel, message) abort
|
||||||
let l:info = ch_info(a:channel)
|
let l:info = ch_info(a:channel)
|
||||||
let l:address = l:info.hostname . l:info.address
|
let l:address = l:info.hostname . l:info.address
|
||||||
let l:conn = filter(s:connections[:], 'v:val.address ==# l:address')[0]
|
let l:conn = s:FindConnection('id', l:address)
|
||||||
|
|
||||||
call ale#lsp#HandleMessage(l:conn, a:message)
|
call ale#lsp#HandleMessage(l:conn, a:message)
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:HandleCommandMessage(job_id, message) abort
|
function! s:HandleCommandMessage(job_id, message) abort
|
||||||
let l:conn = filter(s:connections[:], 'v:val.job_id == a:job_id')[0]
|
let l:conn = s:FindConnection('id', a:job_id)
|
||||||
|
|
||||||
call ale#lsp#HandleMessage(l:conn, a:message)
|
call ale#lsp#HandleMessage(l:conn, a:message)
|
||||||
endfunction
|
endfunction
|
||||||
@ -171,66 +178,37 @@ function! ale#lsp#StartProgram(executable, command, callback) abort
|
|||||||
return 0
|
return 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:matches = filter(s:connections[:], 'v:val.executable ==# a:executable')
|
let l:conn = s:FindConnection('executable', a:executable)
|
||||||
|
|
||||||
" Get the current connection or a new one.
|
" Get the current connection or a new one.
|
||||||
let l:conn = !empty(l:matches) ? l:matches[0] : s:NewConnection()
|
let l:conn = !empty(l:conn) ? l:conn : s:NewConnection()
|
||||||
let l:conn.executable = a:executable
|
let l:conn.executable = a:executable
|
||||||
let l:conn.callback = a:callback
|
|
||||||
|
|
||||||
if !ale#job#IsRunning(l:conn.job_id)
|
if !has_key(l:conn, 'id') || !ale#job#IsRunning(l:conn.id)
|
||||||
let l:options = {
|
let l:options = {
|
||||||
\ 'mode': 'raw',
|
\ 'mode': 'raw',
|
||||||
\ 'out_cb': function('s:HandleCommandMessage'),
|
\ 'out_cb': function('s:HandleCommandMessage'),
|
||||||
\}
|
\}
|
||||||
let l:job_id = ale#job#Start(a:command, l:options)
|
let l:job_id = ale#job#Start(a:command, l:options)
|
||||||
else
|
else
|
||||||
let l:job_id = l:conn.job_id
|
let l:job_id = l:conn.id
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if l:job_id <= 0
|
if l:job_id <= 0
|
||||||
return 0
|
return 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:conn.job_id = l:job_id
|
let l:conn.id = l:job_id
|
||||||
|
let l:conn.callback = a:callback
|
||||||
|
|
||||||
return l:job_id
|
return l:job_id
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Send a message to a server with a given executable, and a command for
|
|
||||||
" running the executable.
|
|
||||||
"
|
|
||||||
" Returns -1 when a message is sent, but no response is expected
|
|
||||||
" 0 when the message is not sent and
|
|
||||||
" >= 1 with the message ID when a response is expected.
|
|
||||||
function! ale#lsp#SendMessageToProgram(executable, message) abort
|
|
||||||
let [l:id, l:data] = ale#lsp#CreateMessageData(a:message)
|
|
||||||
|
|
||||||
let l:matches = filter(s:connections[:], 'v:val.executable ==# a:executable')
|
|
||||||
|
|
||||||
" No connection is currently open.
|
|
||||||
if empty(l:matches)
|
|
||||||
return 0
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Get the current connection or a new one.
|
|
||||||
let l:conn = l:matches[0]
|
|
||||||
let l:conn.executable = a:executable
|
|
||||||
|
|
||||||
if get(l:conn, 'job_id', 0) == 0
|
|
||||||
return 0
|
|
||||||
endif
|
|
||||||
|
|
||||||
call ale#job#SendRaw(l:conn.job_id, l:data)
|
|
||||||
|
|
||||||
return l:id == 0 ? -1 : l:id
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Connect to an address and set up a callback for handling responses.
|
" Connect to an address and set up a callback for handling responses.
|
||||||
function! ale#lsp#ConnectToAddress(address, callback) abort
|
function! ale#lsp#ConnectToAddress(address, callback) abort
|
||||||
let l:matches = filter(s:connections[:], 'v:val.address ==# a:address')
|
let l:conn = s:FindConnection('id', a:address)
|
||||||
" Get the current connection or a new one.
|
" Get the current connection or a new one.
|
||||||
let l:conn = !empty(l:matches) ? l:matches[0] : s:NewConnection()
|
let l:conn = !empty(l:conn) ? l:conn : s:NewConnection()
|
||||||
|
|
||||||
if !has_key(l:conn, 'channel') || ch_status(l:conn.channel) !=# 'open'
|
if !has_key(l:conn, 'channel') || ch_status(l:conn.channel) !=# 'open'
|
||||||
let l:conn.channnel = ch_open(a:address, {
|
let l:conn.channnel = ch_open(a:address, {
|
||||||
@ -244,59 +222,41 @@ function! ale#lsp#ConnectToAddress(address, callback) abort
|
|||||||
return 0
|
return 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
let l:conn.id = a:address
|
||||||
let l:conn.callback = a:callback
|
let l:conn.callback = a:callback
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
" Send a message to a server at a given address.
|
" Send a message to an LSP server.
|
||||||
" Notifications do not need to be handled.
|
" Notifications do not need to be handled.
|
||||||
"
|
"
|
||||||
" Returns -1 when a message is sent, but no response is expected
|
" Returns -1 when a message is sent, but no response is expected
|
||||||
" 0 when the message is not sent and
|
" 0 when the message is not sent and
|
||||||
" >= 1 with the message ID when a response is expected.
|
" >= 1 with the message ID when a response is expected.
|
||||||
function! ale#lsp#SendMessageToAddress(address, message) abort
|
function! ale#lsp#Send(conn_id, message) abort
|
||||||
if a:0 > 1
|
let l:conn = s:FindConnection('id', a:conn_id)
|
||||||
throw 'Too many arguments!'
|
|
||||||
endif
|
|
||||||
|
|
||||||
if !a:message[0] && a:0 == 0
|
|
||||||
throw 'A callback must be set for messages which are not notifications!'
|
|
||||||
endif
|
|
||||||
|
|
||||||
let [l:id, l:data] = ale#lsp#CreateMessageData(a:message)
|
let [l:id, l:data] = ale#lsp#CreateMessageData(a:message)
|
||||||
|
|
||||||
let l:matches = filter(s:connections[:], 'v:val.address ==# a:address')
|
if has_key(l:conn, 'executable')
|
||||||
|
call ale#job#SendRaw(l:conn.id, l:data)
|
||||||
" No connection is currently open.
|
elseif has_key(l:conn, 'channel') && ch_status(l:conn.channnel) ==# 'open'
|
||||||
if empty(l:matches)
|
" Send the message to the server
|
||||||
|
call ch_sendraw(l:conn.channel, l:data)
|
||||||
|
else
|
||||||
return 0
|
return 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
let l:conn = l:matches[0]
|
|
||||||
|
|
||||||
if ch_status(l:conn.channnel) !=# 'open'
|
|
||||||
return 0
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Send the message to the server
|
|
||||||
call ch_sendraw(l:conn.channel, l:data)
|
|
||||||
|
|
||||||
return l:id == 0 ? -1 : l:id
|
return l:id == 0 ? -1 : l:id
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! ale#lsp#OpenTSServerDocumentIfNeeded(executable, buffer) abort
|
function! ale#lsp#OpenTSServerDocumentIfNeeded(conn_id, buffer) abort
|
||||||
|
let l:conn = s:FindConnection('id', a:conn_id)
|
||||||
let l:opened = 0
|
let l:opened = 0
|
||||||
let l:matches = filter(s:connections[:], 'v:val.executable ==# a:executable')
|
|
||||||
|
|
||||||
" Send the command for opening the document only if needed.
|
|
||||||
if !empty(l:matches) && index(l:matches[0].open_documents, a:buffer) < 0
|
|
||||||
call ale#lsp#SendMessageToProgram(
|
|
||||||
\ a:executable,
|
|
||||||
\ ale#lsp#tsserver_message#Open(a:buffer),
|
|
||||||
\)
|
|
||||||
call add(l:matches[0].open_documents, a:buffer)
|
|
||||||
|
|
||||||
|
if !empty(l:conn) && index(l:conn.open_documents, a:buffer) < 0
|
||||||
|
call ale#lsp#Send(a:conn_id, ale#lsp#tsserver_message#Open(a:buffer))
|
||||||
|
call add(l:conn.open_documents, a:buffer)
|
||||||
let l:opened = 1
|
let l:opened = 1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user