Close #4458 - Add an ALEStopLSP command

Add an ALEStopLSP command to stop all language servers that match a
given name. Completions are available for the command. This makes it
possible to keep other language servers running other than the one
you're interested in stopping.
This commit is contained in:
w0rp
2023-09-16 17:03:02 +01:00
parent be69af2705
commit 1799f8bec6
5 changed files with 216 additions and 46 deletions

View File

@@ -1,9 +1,16 @@
" Author: w0rp <dev@w0rp.com>
" Description: Functions for resetting LSP servers.
function! s:Message(message) abort
call ale#util#Execute('echom ' . string(a:message))
endfunction
" Stop all LSPs and remove all of the data for them.
function! ale#lsp#reset#StopAllLSPs() abort
call ale#lsp#StopAll()
if exists('*ale#definition#ClearLSPData')
" Clear the mapping for connections, etc.
" Clear the go to definition mapping for everything.
call ale#definition#ClearLSPData()
endif
@@ -25,3 +32,61 @@ function! ale#lsp#reset#StopAllLSPs() abort
endfor
endif
endfunction
function! ale#lsp#reset#Complete(arg, line, pos) abort
let l:linter_map = ale#lsp_linter#GetLSPLinterMap()
let l:candidates = map(values(l:linter_map), {_, linter -> linter.name})
call uniq(sort(l:candidates))
call filter(l:candidates, {_, name -> name =~? a:arg})
return l:candidates
endfunction
function! ale#lsp#reset#StopLSP(name, bang) abort
let l:linter_map = ale#lsp_linter#GetLSPLinterMap()
let l:matched = filter(
\ items(l:linter_map),
\ {_, item -> item[1].name is# a:name}
\)
if empty(l:matched)
if a:bang isnot# '!'
call s:Message('No running language server with name: ' . a:name)
endif
return
endif
" Stop LSP connections first.
for [l:conn_id, l:linter] in l:matched
call ale#lsp#Stop(l:conn_id)
endfor
if exists('*ale#definition#ClearLSPData')
" Clear the go to definition mapping for everything.
call ale#definition#ClearLSPData()
endif
" Remove connections from the lsp_linter map.
for [l:conn_id, l:linter] in l:matched
call remove(l:linter_map, l:conn_id)
endfor
" Remove the problems for the LSP linters in every buffer.
for [l:buffer_string, l:info] in items(g:ale_buffer_info)
let l:buffer = str2nr(l:buffer_string)
let l:should_clear_buffer = 0
for l:item in l:info.loclist
if l:item.linter_name is# a:name
let l:should_clear_buffer = 1
break
endif
endfor
if l:should_clear_buffer
call ale#engine#HandleLoclist(a:name, l:buffer, [], 0)
endif
endfor
endfunction

View File

@@ -8,13 +8,9 @@ if !has_key(s:, 'lsp_linter_map')
let s:lsp_linter_map = {}
endif
" A Dictionary to track one-shot handlers for custom LSP requests
let s:custom_handlers_map = get(s:, 'custom_handlers_map', {})
" Clear LSP linter data for the linting engine.
function! ale#lsp_linter#ClearLSPData() abort
let s:lsp_linter_map = {}
let s:custom_handlers_map = {}
endfunction
" Only for internal use.
@@ -82,7 +78,12 @@ function! s:ShouldIgnoreDiagnostics(buffer, linter) abort
endfunction
function! s:HandleLSPDiagnostics(conn_id, response) abort
let l:linter = s:lsp_linter_map[a:conn_id]
let l:linter = get(s:lsp_linter_map, a:conn_id)
if empty(l:linter)
return
endif
let l:filename = ale#util#ToResource(a:response.params.uri)
let l:escaped_name = escape(
\ fnameescape(l:filename),
@@ -540,9 +541,14 @@ endfunction
function! s:HandleLSPResponseToCustomRequests(conn_id, response) abort
if has_key(a:response, 'id')
\&& has_key(s:custom_handlers_map, a:response.id)
let l:Handler = remove(s:custom_handlers_map, a:response.id)
call l:Handler(a:response)
" Get the custom handlers Dictionary from the linter map.
let l:linter = get(s:lsp_linter_map, a:conn_id, {})
let l:custom_handlers = get(l:linter, 'custom_handlers', {})
if has_key(l:custom_handlers, a:response.id)
let l:Handler = remove(l:custom_handlers, a:response.id)
call l:Handler(a:response)
endif
endif
endfunction
@@ -553,7 +559,17 @@ function! s:OnReadyForCustomRequests(args, linter, lsp_details) abort
if l:request_id > 0 && has_key(a:args, 'handler')
let l:Callback = function('s:HandleLSPResponseToCustomRequests')
call ale#lsp#RegisterCallback(l:id, l:Callback)
let s:custom_handlers_map[l:request_id] = a:args.handler
" Remember the linter this connection is for.
let s:lsp_linter_map[l:id] = a:linter
" Add custom_handlers to the linter Dictionary.
if !has_key(a:linter, 'custom_handlers')
let a:linter.custom_handlers = {}
endif
" Put the handler function in the map to call later.
let a:linter.custom_handlers[l:request_id] = a:args.handler
endif
endfunction