Skip to content

Commit

Permalink
Clean local state when server exits
Browse files Browse the repository at this point in the history
Partially addresses #7

- Change s:completion_waiting variable to a Map (used as a Set) by
  filetype so that only the filetype(s) impacted by a server can be
  cleaned when it exits.
- Add lsc#diagnostics#clean and lsc#complete#clean methods to clean up
  script owned state related to a server
- Split up onExit method to clean up server.vim local state, then find
  the command and filetypes related to that server and clean up by
  filetype.
- Fix a bug clearing s:initialized_servers
  • Loading branch information
natebosch committed Jun 4, 2017
1 parent 18124a1 commit 36b1320
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 11 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# 0.2.1-dev

- Clean up local state when a language server exits.

# 0.2.0

- More detail in completion suggestions, doc comment in preview window.
Expand Down
29 changes: 24 additions & 5 deletions autoload/lsc/complete.vim
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ function! lsc#complete#textChanged() abort
endfunction

function! s:typedCharacter() abort
if s:isTrigger(s:next_char) || (s:isCompletable() && !s:completion_waiting)
if s:isTrigger(s:next_char)
\ || (s:isCompletable() && !has_key(s:completion_waiting, &filetype))
let b:lsc_is_completing = v:true
call s:startCompletion()
else
Expand All @@ -30,12 +31,28 @@ endfunction

if !exists('s:initialized')
let s:next_char = ''
let s:completion_waiting = v:false
" filetype -> ?, used as a Set
let s:completion_waiting = {}
let s:completion_id = 1
let s:completion_canceled = v:false
let s:initialized = v:true
endif

" Clean state associated with a server.
function! lsc#complete#clean(filetype) abort
call s:MarkNotCompleting(a:filetype)
endfunction

function s:MarkCompleting(filetype) abort
let s:completion_waiting[a:filetype] = v:true
endfunction

function s:MarkNotCompleting(filetype) abort
if has_key(s:completion_waiting, a:filetype)
unlet s:completion_waiting[a:filetype]
endif
endfunction

" TODO: Make this customizable
function! s:isTrigger(char) abort
return a:char == '.'
Expand Down Expand Up @@ -75,10 +92,12 @@ endfunction
function! s:startCompletion() abort
let s:completion_id += 1
let s:completion_canceled = v:false
let s:completion_waiting = v:true
let data = {'old_pos': getcurpos(), 'completion_id': s:completion_id}
call s:MarkCompleting(&filetype)
let data = {'old_pos': getcurpos(),
\ 'completion_id': s:completion_id,
\ 'filetype': &filetype}
function data.trigger(completions)
let s:completion_waiting = v:false
call s:MarkNotCompleting(self.filetype)
if s:isCompletionValid(self.old_pos, self.completion_id)
call s:SuggestCompletions(a:completions)
else
Expand Down
7 changes: 7 additions & 0 deletions autoload/lsc/diagnostics.vim
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ function! lsc#diagnostics#convert(diagnostic) abort
\ 'message': a:diagnostic.message, 'type': type}
endfunction

function! lsc#diagnostics#clean(filetype) abort
for buffer in getbufinfo({'loaded': v:true})
if getbufvar(buffer.bufnr, '&filetype') != a:filetype | continue | endif
call lsc#diagnostics#setForFile(buffer.name, [])
endfor
endfunction

" Converts between an internal diagnostic and an item for the location list.
function! s:locationListItem(bufnr, diagnostic) abort
return {'bufnr': a:bufnr,
Expand Down
22 changes: 16 additions & 6 deletions autoload/lsc/server.vim
Original file line number Diff line number Diff line change
Expand Up @@ -87,23 +87,33 @@ function! s:RunCommand(command) abort
\ params, data.onInitialize, v:true)
endfunction

" Clean up stored state about a running server.
" Find the command for `job` and clean up it's state
function! lsc#server#onExit(job, status) abort
let channel = job_getchannel(a:job)
let ch_id = ch_info(channel)['id']
unlet s:channel_buffers[ch_id]
for command in keys(s:running_servers)
if s:running_servers[command] == a:job
unlet s:running_servers[command]
let initialize = index(s:initialized_servers, command)
if initialize > 0
call remove(s:initialized_servers, initialize)
endif
call s:OnCommandExit(command)
return
endif
endfor
endfunction

" Clean up stored state about a running server.
function! s:OnCommandExit(command) abort
unlet s:running_servers[a:command]
let initialize = index(s:initialized_servers, a:command)
if initialize >= 0
call remove(s:initialized_servers, initialize)
endif
for filetype in keys(g:lsc_server_commands)
if g:lsc_server_commands[filetype] != a:command | continue | endif
call lsc#complete#clean(filetype)
call lsc#diagnostics#clean(filetype)
endfor
endfunction

" Append to the buffer for the channel and try to consume a message.
function! lsc#server#channelCallback(channel, message) abort
let ch_id = ch_info(a:channel)['id']
Expand Down

0 comments on commit 36b1320

Please sign in to comment.