Close #829 - Close LSP documents when buffers are deleted
This commit is contained in:
parent
07b596efb5
commit
381fe1badf
3 changed files with 209 additions and 0 deletions
|
@ -710,6 +710,10 @@ function! ale#engine#Cleanup(buffer) abort
|
|||
return
|
||||
endif
|
||||
|
||||
if exists('*ale#lsp#CloseDocument')
|
||||
call ale#lsp#CloseDocument(a:buffer)
|
||||
endif
|
||||
|
||||
if !has_key(g:ale_buffer_info, a:buffer)
|
||||
return
|
||||
endif
|
||||
|
|
|
@ -484,6 +484,35 @@ function! ale#lsp#OpenDocument(conn_id, buffer, language_id) abort
|
|||
return l:opened
|
||||
endfunction
|
||||
|
||||
" Notify LSP servers or tsserver that a document is closed, if opened before.
|
||||
" If a document is closed, 1 will be returned, otherwise 0 will be returned.
|
||||
"
|
||||
" Only the buffer number is required here. A message will be sent to every
|
||||
" language server that was notified previously of the document being opened.
|
||||
function! ale#lsp#CloseDocument(buffer) abort
|
||||
let l:closed = 0
|
||||
|
||||
" The connection keys are sorted so the messages are easier to test, and
|
||||
" so messages are sent in a consistent order.
|
||||
for l:conn_id in sort(keys(s:connections))
|
||||
let l:conn = s:connections[l:conn_id]
|
||||
|
||||
if l:conn.initialized && has_key(l:conn.open_documents, a:buffer)
|
||||
if l:conn.is_tsserver
|
||||
let l:message = ale#lsp#tsserver_message#Close(a:buffer)
|
||||
else
|
||||
let l:message = ale#lsp#message#DidClose(a:buffer)
|
||||
endif
|
||||
|
||||
call ale#lsp#Send(l:conn_id, l:message)
|
||||
call remove(l:conn.open_documents, a:buffer)
|
||||
let l:closed = 1
|
||||
endif
|
||||
endfor
|
||||
|
||||
return l:closed
|
||||
endfunction
|
||||
|
||||
" Notify LSP servers or tsserver that a document has changed, if needed.
|
||||
" If a notification is sent, 1 will be returned, otherwise 0 will be returned.
|
||||
function! ale#lsp#NotifyForChanges(conn_id, buffer) abort
|
||||
|
|
176
test/lsp/test_closing_documents.vader
Normal file
176
test/lsp/test_closing_documents.vader
Normal file
|
@ -0,0 +1,176 @@
|
|||
Before:
|
||||
runtime autoload/ale/lsp.vim
|
||||
|
||||
let g:message_list = []
|
||||
|
||||
function! MarkAllConnectionsInitialized() abort
|
||||
for l:conn in values(ale#lsp#GetConnections())
|
||||
let l:conn.initialized = 1
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! MarkDocumentOpened() abort
|
||||
for l:conn in values(ale#lsp#GetConnections())
|
||||
let l:conn.open_documents[bufnr('')] = 1
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! ale#lsp#Send(conn_id, message) abort
|
||||
let l:connections = ale#lsp#GetConnections()
|
||||
|
||||
if !l:connections[a:conn_id].initialized
|
||||
throw 'LSP server not initialized yet!'
|
||||
endif
|
||||
|
||||
call add(g:message_list, [a:conn_id] + a:message)
|
||||
endfunction
|
||||
|
||||
call ale#lsp#ResetConnections()
|
||||
|
||||
After:
|
||||
unlet! g:message_list
|
||||
delfunction MarkAllConnectionsInitialized
|
||||
delfunction MarkDocumentOpened
|
||||
|
||||
call ale#lsp#ResetConnections()
|
||||
|
||||
runtime autoload/ale/lsp.vim
|
||||
|
||||
Execute(No errors should be thrown if the connection is not initialized):
|
||||
call ale#lsp#Register('command', '/foo', {})
|
||||
call MarkDocumentOpened()
|
||||
|
||||
call ale#engine#Cleanup(bufnr(''))
|
||||
AssertEqual [], g:message_list
|
||||
|
||||
Execute(No messages should be sent if the document wasn't opened):
|
||||
call ale#lsp#Register('command', '/foo', {})
|
||||
call MarkAllConnectionsInitialized()
|
||||
|
||||
call ale#engine#Cleanup(bufnr(''))
|
||||
AssertEqual [], g:message_list
|
||||
|
||||
Execute(A message should be sent if the document was opened):
|
||||
call ale#lsp#Register('command', '/foo', {})
|
||||
call MarkAllConnectionsInitialized()
|
||||
|
||||
call ale#lsp#OpenDocument('command:/foo', bufnr(''), 'lang')
|
||||
call ale#engine#Cleanup(bufnr(''))
|
||||
" We should only send the message once.
|
||||
call ale#engine#Cleanup(bufnr(''))
|
||||
|
||||
AssertEqual
|
||||
\ [
|
||||
\ ['command:/foo', 1, 'textDocument/didOpen', {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': ale#path#ToURI(expand('%:p')),
|
||||
\ 'version': g:ale_lsp_next_version_id - 1,
|
||||
\ 'languageId': 'lang',
|
||||
\ 'text': "\n",
|
||||
\ },
|
||||
\ }],
|
||||
\ ['command:/foo', 1, 'textDocument/didClose', {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': ale#path#ToURI(expand('%:p')),
|
||||
\ },
|
||||
\ }],
|
||||
\ ],
|
||||
\ g:message_list
|
||||
|
||||
Execute(A message should be sent if the document was opened for tsserver):
|
||||
call ale#lsp#Register('command', '/foo', {})
|
||||
call ale#lsp#MarkConnectionAsTsserver('command:/foo')
|
||||
|
||||
call ale#lsp#OpenDocument('command:/foo', bufnr(''), 'lang')
|
||||
call ale#engine#Cleanup(bufnr(''))
|
||||
" We should only send the message once.
|
||||
call ale#engine#Cleanup(bufnr(''))
|
||||
|
||||
AssertEqual
|
||||
\ [
|
||||
\ ['command:/foo', 1, 'ts@open', {'file': expand('%:p')}],
|
||||
\ ['command:/foo', 1, 'ts@close', {'file': expand('%:p')}],
|
||||
\ ],
|
||||
\ g:message_list
|
||||
|
||||
Execute(Re-opening and closing the documents should work):
|
||||
call ale#lsp#Register('command', '/foo', {})
|
||||
call MarkAllConnectionsInitialized()
|
||||
|
||||
call ale#lsp#OpenDocument('command:/foo', bufnr(''), 'lang')
|
||||
call ale#engine#Cleanup(bufnr(''))
|
||||
call ale#lsp#OpenDocument('command:/foo', bufnr(''), 'lang')
|
||||
call ale#engine#Cleanup(bufnr(''))
|
||||
|
||||
AssertEqual
|
||||
\ [
|
||||
\ ['command:/foo', 1, 'textDocument/didOpen', {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': ale#path#ToURI(expand('%:p')),
|
||||
\ 'version': g:ale_lsp_next_version_id - 2,
|
||||
\ 'languageId': 'lang',
|
||||
\ 'text': "\n",
|
||||
\ },
|
||||
\ }],
|
||||
\ ['command:/foo', 1, 'textDocument/didClose', {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': ale#path#ToURI(expand('%:p')),
|
||||
\ },
|
||||
\ }],
|
||||
\ ['command:/foo', 1, 'textDocument/didOpen', {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': ale#path#ToURI(expand('%:p')),
|
||||
\ 'version': g:ale_lsp_next_version_id - 1,
|
||||
\ 'languageId': 'lang',
|
||||
\ 'text': "\n",
|
||||
\ },
|
||||
\ }],
|
||||
\ ['command:/foo', 1, 'textDocument/didClose', {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': ale#path#ToURI(expand('%:p')),
|
||||
\ },
|
||||
\ }],
|
||||
\ ],
|
||||
\ g:message_list
|
||||
|
||||
Execute(Messages for closing documents should be sent to each server):
|
||||
call ale#lsp#Register('command', '/foo', {})
|
||||
call ale#lsp#Register('command', '/bar', {})
|
||||
call MarkAllConnectionsInitialized()
|
||||
|
||||
call ale#lsp#OpenDocument('command:/foo', bufnr(''), 'lang')
|
||||
call ale#lsp#OpenDocument('command:/bar', bufnr(''), 'lang')
|
||||
call ale#engine#Cleanup(bufnr(''))
|
||||
" We should only send the message once.
|
||||
call ale#engine#Cleanup(bufnr(''))
|
||||
|
||||
AssertEqual
|
||||
\ [
|
||||
\ ['command:/foo', 1, 'textDocument/didOpen', {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': ale#path#ToURI(expand('%:p')),
|
||||
\ 'version': g:ale_lsp_next_version_id - 2,
|
||||
\ 'languageId': 'lang',
|
||||
\ 'text': "\n",
|
||||
\ },
|
||||
\ }],
|
||||
\ ['command:/bar', 1, 'textDocument/didOpen', {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': ale#path#ToURI(expand('%:p')),
|
||||
\ 'version': g:ale_lsp_next_version_id - 1,
|
||||
\ 'languageId': 'lang',
|
||||
\ 'text': "\n",
|
||||
\ },
|
||||
\ }],
|
||||
\ ['command:/bar', 1, 'textDocument/didClose', {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': ale#path#ToURI(expand('%:p')),
|
||||
\ },
|
||||
\ }],
|
||||
\ ['command:/foo', 1, 'textDocument/didClose', {
|
||||
\ 'textDocument': {
|
||||
\ 'uri': ale#path#ToURI(expand('%:p')),
|
||||
\ },
|
||||
\ }],
|
||||
\ ],
|
||||
\ g:message_list
|
Reference in a new issue