From 187ec56b1ad8b6ffc64ed41ece48af41dce88285 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Thu, 17 Feb 2022 17:54:35 -0800 Subject: [PATCH] Add support for the LspServerRestart command to restart the LSP server --- README.md | 1 + autoload/handlers.vim | 8 +++++++- autoload/lsp.vim | 38 +++++++++++++++++++++++++++++++++++--- autoload/lspserver.vim | 39 ++++++++++++++++++++++++++++----------- doc/lsp.txt | 15 ++++++++++----- plugin/lsp.vim | 6 ++++++ 6 files changed, 87 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 0f1614a..380bfdd 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,7 @@ Command|Description :LspWorkspaceAddFolder `{folder}`| Add a folder to the workspace :LspWorkspaceRemoveFolder `{folder}`|Remove a folder from the workspace :LspWorkspaceListFolders|Show the list of folders in the workspace +:LspServerRestart|Restart the LSP server for the current buffer ## Similar Vim LSP Plugins diff --git a/autoload/handlers.vim b/autoload/handlers.vim index ce0b20c..2995634 100644 --- a/autoload/handlers.vim +++ b/autoload/handlers.vim @@ -122,6 +122,11 @@ def ProcessInitializeReply(lspserver: dict, req: dict, reply: dict, req: dict, reply: dict): void + return +enddef + # process the 'textDocument/definition' / 'textDocument/declaration' / # 'textDocument/typeDefinition' and 'textDocument/implementation' replies from # the LSP server @@ -674,6 +679,7 @@ export def ProcessReply(lspserver: dict, req: dict, reply: dict): var lsp_reply_handlers: dict = { 'initialize': function('ProcessInitializeReply'), + 'shutdown': function('ProcessShutdownReply'), 'textDocument/definition': function('ProcessDefDeclReply'), 'textDocument/declaration': function('ProcessDefDeclReply'), 'textDocument/typeDefinition': function('ProcessDefDeclReply'), @@ -700,7 +706,7 @@ export def ProcessReply(lspserver: dict, req: dict, reply: dict): if lsp_reply_handlers->has_key(req.method) lsp_reply_handlers[req.method](lspserver, req, reply) else - util.ErrMsg("Error: Unsupported reply received from LSP server: " .. reply->string()) + util.ErrMsg("Error: Unsupported reply received from LSP server: " .. reply->string() .. " for request: " .. req->string()) endif enddef diff --git a/autoload/lsp.vim b/autoload/lsp.vim index 6005ec0..85fe67b 100644 --- a/autoload/lsp.vim +++ b/autoload/lsp.vim @@ -401,10 +401,12 @@ enddef # Notify LSP server to remove a file export def RemoveFile(bnr: number): void var lspserver: dict = buf.BufLspServerGet(bnr) - if lspserver->empty() || !lspserver.running + if lspserver->empty() return endif - lspserver.textdocDidClose(bnr) + if lspserver.running + lspserver.textdocDidClose(bnr) + endif diag.DiagRemoveFile(lspserver, bnr) buf.BufLspServerRemove(bnr) enddef @@ -418,6 +420,35 @@ export def StopAllServers() endfor enddef +# Restart the LSP server for the current buffer +export def RestartServer() + var lspserver: dict = CurbufGetServerChecked() + if lspserver->empty() + return + endif + + # Stop the server + lspserver.stopServer() + + # Remove all the buffers with the same file type as the current buffer + var ftype: string = &filetype + for binfo in getbufinfo() + if getbufvar(binfo.bufnr, '&filetype') == ftype + RemoveFile(binfo.bufnr) + endif + endfor + + # Start the server again + lspserver.startServer(true) + + # Add all the buffers with the same file type as the current buffer + for binfo in getbufinfo({bufloaded: 1}) + if getbufvar(binfo.bufnr, '&filetype') == ftype + AddFile(binfo.bufnr) + endif + endfor +enddef + # Register a LSP server for one or more file types export def AddServer(serverList: list>) for server in serverList @@ -779,7 +810,8 @@ export def Rename() return endif - var newName: string = input("Rename symbol: ", expand('')) + var sym: string = expand('') + var newName: string = input("Rename symbol '" .. sym .. "' to: ", sym) if newName == '' return endif diff --git a/autoload/lspserver.vim b/autoload/lspserver.vim index 6d9f1e8..2077722 100644 --- a/autoload/lspserver.vim +++ b/autoload/lspserver.vim @@ -70,14 +70,16 @@ enddef # LSP server exit callback def Exit_cb(lspserver: dict, job: job, status: number): void util.WarnMsg("LSP server exited with status " .. status) - lspserver.job = v:null lspserver.running = false lspserver.ready = false lspserver.requests = {} enddef # Start a LSP server -def StartServer(lspserver: dict): number +# +# If 'isSync' is true, then waits for the server to send the initialize +# reponse message. +def StartServer(lspserver: dict, isSync: bool = false): number if lspserver.running util.WarnMsg("LSP server for is already running") return 0 @@ -109,20 +111,23 @@ def StartServer(lspserver: dict): number return 1 endif - # wait for the LSP server to start + # wait a little for the LSP server to start sleep 10m lspserver.job = job lspserver.running = true - lspserver.initServer() + lspserver.initServer(isSync) return 0 enddef # Request: 'initialize' # Param: InitializeParams -def InitServer(lspserver: dict) +# +# If 'isSync' is true, then waits for the server to send the initialize +# reponse message. +def InitServer(lspserver: dict, isSync: bool = false) var req = lspserver.createRequest('initialize') # client capabilities (ClientCapabilities) @@ -171,6 +176,9 @@ def InitServer(lspserver: dict) req.params->extend(initparams) lspserver.sendMessage(req) + if isSync + lspserver.waitForReponse(req) + endif enddef # Send a "initialized" LSP notification @@ -185,6 +193,7 @@ enddef def ShutdownServer(lspserver: dict): void var req = lspserver.createRequest('shutdown') lspserver.sendMessage(req) + lspserver.waitForReponse(req) enddef # Send a 'exit' notification to the LSP server @@ -201,15 +210,23 @@ def StopServer(lspserver: dict): number return 0 endif + # Send the shutdown request to the server lspserver.shutdownServer() - # Wait for the server to process the shutodwn request - sleep 1 - + # Notify the server to exit lspserver.exitServer() - lspserver.job->job_stop() - lspserver.job = v:null + # Wait for the server to process the exit notification and exit for a + # maximum of 2 seconds. + var maxCount: number = 1000 + while lspserver.job->job_status() == 'run' && maxCount > 0 + sleep 2m + maxCount -= 1 + endwhile + + if lspserver.job->job_status() == 'run' + lspserver.job->job_stop() + endif lspserver.running = false lspserver.ready = false lspserver.requests = {} @@ -921,7 +938,7 @@ def SelectionRange(lspserver: dict, fname: string) var req = lspserver.createRequest('textDocument/selectionRange') # interface SelectionRangeParams # interface TextDocumentIdentifier - req.params->extend({textDocument: {uri: util.LspFileToUri(fname)}, positions: [s:GetLspPosition()]}) + req.params->extend({textDocument: {uri: util.LspFileToUri(fname)}, positions: [GetLspPosition()]}) lspserver.sendMessage(req) lspserver.waitForReponse(req) diff --git a/doc/lsp.txt b/doc/lsp.txt index 411ee85..f463686 100644 --- a/doc/lsp.txt +++ b/doc/lsp.txt @@ -2,7 +2,7 @@ Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com) For Vim version 8.2.2342 and above -Last change: Feb 4, 2022 +Last change: Feb 17, 2022 ============================================================================== *lsp-license* @@ -126,6 +126,7 @@ The following commands are provided: Show the list of folders in the workspace :LspShowServerCapabilities Display the list of capabilities of a LSP server. +:LspServerRestart Restart the LSP server for the current buffer. ============================================================================== 4. Configuration *lsp-configuration* @@ -485,17 +486,21 @@ diagnostic messages, you can add the following line to your .vimrc file: :LspWorkspaceRemoveFolder {folder} Remove a folder from the workspace - *:LspWorkspaceListFolders* -:LspWorkspaceListFolders +:LspWorkspaceListFolders *:LspWorkspaceListFolders* Show the list of folders in the workspace. - *:LspShowServerCapabilities* -:LspShowServerCapabilities +:LspShowServerCapabilities *:LspShowServerCapabilities* Display the list of capabilities of a LSP server. The server capabilities are described in the LSP protocol specification under the "ServerCapabilities" interface. + *:LspServerRestart* +:LspServerRestart Restart (stop and then start) the LSP server for the + current buffer. All the loaded buffers with the same + filetype as the current buffer are added back to the + server. + ============================================================================== 6. Insert mode completion diff --git a/plugin/lsp.vim b/plugin/lsp.vim index 83b98d7..7d241ea 100644 --- a/plugin/lsp.vim +++ b/plugin/lsp.vim @@ -16,6 +16,7 @@ if has('patch-8.2.4257') opt.lspOptions = lspoptions.lspOptions lspf.enableServerTrace = lsp.EnableServerTrace lspf.addServer = lsp.AddServer + lspf.restartServer = lsp.RestartServer lspf.LspServerReady = lsp.ServerReady lspf.addFile = lsp.AddFile lspf.removeFile = lsp.RemoveFile @@ -55,6 +56,7 @@ elseif has('patch-8.2.4019') opt.lspOptions = opt_import.lspOptions lspf.enableServerTrace = lsp_import.EnableServerTrace lspf.addServer = lsp_import.AddServer + lspf.restartServer = lsp_import.RestartServer lspf.LspServerReady = lsp_import.ServerReady lspf.addFile = lsp_import.AddFile lspf.removeFile = lsp_import.RemoveFile @@ -90,6 +92,7 @@ else import {lspOptions, OptionsSet} from '../autoload/lspoptions.vim' import {EnableServerTrace, AddServer, + RestartServer, ServerReady, AddFile, RemoveFile, @@ -126,6 +129,7 @@ else opt.lspOptions = lspOptions lspf.enableServerTrace = EnableServerTrace lspf.addServer = AddServer + lspf.restartServer = RestartServer lspf.LspServerReady = ServerReady lspf.addFile = AddFile lspf.removeFile = RemoveFile @@ -182,6 +186,7 @@ enddef var TshowServers = lspf.showServers var TshowServerCapabilities = lspf.showServerCapabilities +var TrestartServer = lspf.restartServer var TsetTraceServer = lspf.setTraceServer var TaddFile = lspf.addFile var TremoveFile = lspf.removeFile @@ -229,6 +234,7 @@ augroup END # LSP commands command! -nargs=0 -bar LspShowServers call TshowServers() command! -nargs=0 -bar LspShowServerCapabilities call TshowServerCapabilities() +command! -nargs=0 -bar LspServerRestart call TrestartServer() command! -nargs=1 -bar LspSetTrace call TsetTraceServer() command! -nargs=0 -bar LspGotoDefinition call TgotoDefinition(v:false) command! -nargs=0 -bar LspGotoDeclaration call TgotoDeclaration(v:false) -- 2.48.1