README.md | 3 +-- autoload/lsp/handlers.vim | 49 ++++++++++++++++++++++++++++++++----------------- autoload/lsp/lsp.vim | 20 ++++++++++++++------ autoload/lsp/lspserver.vim | 32 ++++++++++++++++++++++++++------ doc/lsp.txt | 32 +++++++++++++++++--------------- plugin/lsp.vim | 18 +++++++++++++++--- diff --git a/README.md b/README.md index 73d382e3b53ef415c55e1a1052f153d7d77b41ef..9f66a9001af384db97cf327042fd8b345520eb54 100644 --- a/README.md +++ b/README.md @@ -189,8 +189,7 @@ :LspSelectionShrink|Shrink the current symbol range visual selection. :LspShowAllServers|Display information about all the registered language servers. :LspServerRestart|Restart the language server for the current buffer. :LspShowReferences|Display the list of references to the keyword under cursor in a new location list. -:LspShowServer|Display the language server status for the current buffer. -:LspShowServerCapabilities|Display the language server capabilities for the current buffer. +:LspShowServer|Display the capabilities or messages or status of the language server for the current buffer. :LspShowSignature|Display the signature of the keyword under cursor. :LspSubTypeHierarchy|Display the sub type hierarchy in a popup window. :LspSuperTypeHierarchy|Display the super type hierarchy in a popup window. diff --git a/autoload/lsp/handlers.vim b/autoload/lsp/handlers.vim index 93c4312d9bc3488dc1f29f6c467837178661c774..42c0cbd6e4e5373c62a9e45f1de2e2734d6c1eb0 100644 --- a/autoload/lsp/handlers.vim +++ b/autoload/lsp/handlers.vim @@ -20,11 +20,20 @@ def ProcessDiagNotif(lspserver: dict, reply: dict): void diag.DiagNotification(lspserver, reply.params.uri, reply.params.diagnostics) enddef +# Convert LSP message type to a string +def LspMsgTypeToString(lspMsgType: number): string + var msgStrMap: list = ['', 'Error', 'Warning', 'Info', 'Log'] + var mtype: string = 'Log' + if lspMsgType > 0 && lspMsgType < 5 + mtype = msgStrMap[lspMsgType] + endif + return mtype +enddef + # process a show notification message from the LSP server # Notification: window/showMessage # Param: ShowMessageParams def ProcessShowMsgNotif(lspserver: dict, reply: dict) - var msgType: list = ['', 'Error: ', 'Warning: ', 'Info: ', 'Log: '] if reply.params.type == 4 # ignore log messages from the LSP server (too chatty) # TODO: Add a configuration to control the message level that will be @@ -32,35 +41,41 @@ # displayed. Also store these messages and provide a command to display # them. return endif - var mtype: string = 'Log: ' - if reply.params.type > 0 && reply.params.type < 5 - mtype = msgType[reply.params.type] - endif - - :echomsg $'Lsp {mtype} {reply.params.message}' + var mtype = LspMsgTypeToString(reply.params.type) + :echomsg $'Lsp({lspserver.name}):[{mtype}]: {reply.params.message}' enddef # process a log notification message from the LSP server # Notification: window/logMessage # Param: LogMessageParams def ProcessLogMsgNotif(lspserver: dict, reply: dict) - var msgType: list = ['', 'Error', 'Warning', 'Info', 'Log'] - var mtype: string = 'Log' - if reply.params.type > 0 && reply.params.type < 5 - mtype = msgType[reply.params.type] + var mtype = LspMsgTypeToString(reply.params.type) + var msgs = reply.params.message->split("\n") + + lspserver.messages->add($'{strftime("%m/%d/%y %T")}: [{mtype}]: {msgs[0]}') + lspserver.messages->extend(msgs[1 : ]) + # Keep only the last 500 messages to reduce the memory usage + if lspserver.messages->len() > 500 + lspserver.messages = lspserver.messages[-500 : ] endif +enddef - lspserver.traceLog($'{strftime("%m/%d/%y %T")}: [{mtype}]: {reply.params.message}') +# process the log trace notification messages +# Notification: $/logTrace +# Param: LogTraceParams +def ProcessLogTraceNotif(lspserver: dict, reply: dict) + var msgs = reply.params.message->split("\n") + lspserver.messages->add($'{strftime("%m/%d/%y %T")}: [trace]: {msgs[0]}') + lspserver.messages->extend(msgs[1 : ]) + # Keep only the last 500 messages to reduce the memory usage + if lspserver.messages->len() > 500 + lspserver.messages = lspserver.messages[-500 : ] + endif enddef # process unsupported notification messages def ProcessUnsupportedNotif(lspserver: dict, reply: dict) util.ErrMsg($'Error: Unsupported notification message received from the LSP server ({lspserver.path}), message = {reply->string()}') -enddef - -# process log trace notification messages -def ProcessLogTraceNotif(lspserver: dict, reply: dict) - :echomsg $'Log trace notification: {reply->string()}' enddef # per-filetype private map inside to record if ntf once or not diff --git a/autoload/lsp/lsp.vim b/autoload/lsp/lsp.vim index 62e2f401a10cace9d9d2fec9b4286cbeaa52cae7..ca36ae451ca298110270ba26e886fe6fe34c4ccf 100644 --- a/autoload/lsp/lsp.vim +++ b/autoload/lsp/lsp.vim @@ -155,20 +155,28 @@ :setlocal nomodifiable enddef # Show the status of the LSP server for the current buffer -export def ShowServer() +export def ShowServer(arg: string) var lspserver: dict = buf.CurbufGetServerChecked() if lspserver->empty() :echomsg "LSP Server not found" return endif - var msg = $"LSP server '{lspserver.name}' is " - if lspserver.running - msg ..= 'running' + if arg == '' || arg ==? 'status' + var msg = $"LSP server '{lspserver.name}' is " + if lspserver.running + msg ..= 'running' + else + msg ..= 'not running' + endif + :echomsg msg + elseif arg ==? 'capabilities' + lspserver.showCapabilities() + elseif arg ==? 'messages' + lspserver.showMessages() else - msg ..= 'not running' + util.ErrMsg($'Error: Unsupported argument "{arg}"') endif - :echomsg msg enddef # Get LSP server running status for filetype 'ftype' diff --git a/autoload/lsp/lspserver.vim b/autoload/lsp/lspserver.vim index e652d015fe53dd40fe3de92869e667109ea99818..20e00fd31b9d3facf8f27aace0a6706434607237 100644 --- a/autoload/lsp/lspserver.vim +++ b/autoload/lsp/lspserver.vim @@ -1382,22 +1382,28 @@ var params = cmd lspserver.rpc_a('workspace/executeCommand', params, WorkspaceExecuteReply) enddef -# Display the LSP server capabilities (received during the initialization -# stage). -def ShowCapabilities(lspserver: dict) - var wid = bufwinid('Language-Server-Capabilities') +# Create a new window containing the buffer 'bname' or if the window is +# already present then jump to it. +def OpenScratchWindow(bname: string) + var wid = bufwinid(bname) if wid != -1 wid->win_gotoid() :setlocal modifiable :silent! :%d _ else - :new Language-Server-Capabilities + exe $':new {bname}' :setlocal buftype=nofile :setlocal bufhidden=wipe :setlocal noswapfile :setlocal nonumber nornu :setlocal fdc=0 signcolumn=no endif +enddef + +# Display the LSP server capabilities (received during the initialization +# stage). +def ShowCapabilities(lspserver: dict) + OpenScratchWindow($'LangServer-{lspserver.name}-Capabilities') var l = [] var heading = $"'{lspserver.path}' Language Server Capabilities" var underlines = repeat('=', heading->len()) @@ -1410,6 +1416,18 @@ :setlocal nomodified :setlocal nomodifiable enddef +# Display the log messages received from the LSP server (window/logMessage) +def ShowMessages(lspserver: dict) + if lspserver.messages->empty() + util.WarnMsg($'No messages received from "{lspserver.name}" server') + return + endif + OpenScratchWindow($'LangServer-{lspserver.name}-Messages') + setline(1, lspserver.messages) + :setlocal nomodified + :setlocal nomodifiable +enddef + # Send a 'textDocument/definition' request to the LSP server to get the # location where the symbol under the cursor is defined and return a list of # Dicts in a format accepted by the 'tagfunc' option. @@ -1472,6 +1490,7 @@ peekSymbolFilePopup: -1, callHierarchyType: '', selection: {}, workspaceConfig: workspaceConfig, + messages: [], debug: debug_arg } lspserver.logfile = $'lsp-{lspserver.name}.log' @@ -1542,7 +1561,8 @@ selectionShrink: function(SelectionShrink, [lspserver]), foldRange: function(FoldRange, [lspserver]), executeCommand: function(ExecuteCommand, [lspserver]), workspaceConfigGet: function(WorkspaceConfigGet, [lspserver]), - showCapabilities: function(ShowCapabilities, [lspserver]) + showCapabilities: function(ShowCapabilities, [lspserver]), + showMessages: function(ShowMessages, [lspserver]) }) return lspserver diff --git a/doc/lsp.txt b/doc/lsp.txt index acd4cac959bb57463b1d825e0addcd376b3ed106..0cc668970517c1afc48f13b47ffc49a031e69c7f 100644 --- a/doc/lsp.txt +++ b/doc/lsp.txt @@ -128,11 +128,8 @@ :LspShowAllServers Display the status of all the registered language servers. :LspShowReferences Display the list of references to the keyword under cursor in a new location list. -:LspShowServerCapabilities - Display the language server capabilities for the - current buffer. -:LspShowServer Display the status of the language server for the - current buffer. +:LspShowServer Display the capabilities, status and messages of the + language server for the current buffer. :LspShowSignature Display the signature of the symbol under cursor. :LspSubTypeHierarchy Display the sub type hierarchy in a popup window. :LspSuperTypeHierarchy Display the super type hierarchy in a popup window. @@ -790,17 +787,22 @@ list set > call LspOptionsSet({'useQuickfixForLocations': v:true}) < - -:LspShowServerCapabilities *:LspShowServerCapabilities* - Display the list of language server capabilities for - the current buffer. The server capabilities are - described in the LSP protocol specification under the - "ServerCapabilities" interface. - *:LspShowServer* -:LspShowServer Displays the language server status for the current - buffer. The output shows the path to the language - server executable and the server status. +:LspShowServer {capabilities | messages | status} + capabilities - Display the list of language server + capabilities for the current buffer. + The server capabilities are described + in the LSP protocol specification under + the "ServerCapabilities" interface. + messages - Display the log messages received from + the language server. This includes the + messages received using the + "window/logMessage" and "$/logTrace" + LSP notifications. + status - Display the language server status for + the current buffer. The output shows + the path to the language server + executable and the server status. *:LspShowSignature* :LspShowSignature Displays the signature of the symbol (e.g. a function diff --git a/plugin/lsp.vim b/plugin/lsp.vim index 46ab79d18f3661ba363660837ab737f1d315b2bb..d70cc80c492fe2efdfc4c1c83cf1b07ffa50e48e 100644 --- a/plugin/lsp.vim +++ b/plugin/lsp.vim @@ -44,7 +44,7 @@ def g:LspServerRunning(ftype: string): bool return lsp.ServerRunning(ftype) enddef -# Command line completion function for the LspSetTrace command. +# Command line completion function for the LspServerTrace command. def LspServerTraceComplete(arglead: string, cmdline: string, cursorpos: number): list var l = ['off', 'messages', 'verbose'] if arglead->empty() @@ -54,9 +54,19 @@ return filter(l, (_, val) => val =~ arglead) endif enddef -# Command line completion function for the LspSetTrace command. +# Command line completion function for the LspServerDebug command. def LspServerDebugComplete(arglead: string, cmdline: string, cursorpos: number): list var l = ['errors', 'messages', 'off', 'on'] + if arglead->empty() + return l + else + return filter(l, (_, val) => val =~ arglead) + endif +enddef + +# Command line completion function for the LspShowServer command. +def LspShowServerComplete(arglead: string, cmdline: string, cursorpos: number): list + var l = ['capabilities', 'messages', 'status'] if arglead->empty() return l else @@ -112,8 +122,10 @@ command! -nargs=1 -complete=customlist,LspServerDebugComplete -bar LspServerDebug lsp.ServerDebug() command! -nargs=0 -bar LspServerRestart lsp.RestartServer() command! -nargs=1 -complete=customlist,LspServerTraceComplete -bar LspServerTrace lsp.ServerTraceSet() command! -nargs=0 -bar LspShowReferences lsp.ShowReferences(v:false) +# The :LspShowServerCapabilities command is retained for backward +# compatibility. Remove this in the future. command! -nargs=0 -bar LspShowServerCapabilities lsp.ShowServerCapabilities() -command! -nargs=0 -bar LspShowServer lsp.ShowServer() +command! -nargs=? -complete=customlist,LspShowServerComplete -bar LspShowServer lsp.ShowServer() command! -nargs=0 -bar LspShowAllServers lsp.ShowAllServers() command! -nargs=0 -bar LspShowSignature call LspShowSignature() command! -nargs=0 -bar LspSubTypeHierarchy lsp.TypeHierarchy(0)