]> Sergey Matveev's repositories - vim-lsp.git/commitdiff
Snipper support is set to true for completion matches (by mistake). Include plugin...
authorYegappan Lakshmanan <yegappan@yahoo.com>
Fri, 28 Oct 2022 15:29:11 +0000 (08:29 -0700)
committerYegappan Lakshmanan <yegappan@yahoo.com>
Fri, 28 Oct 2022 15:29:11 +0000 (08:29 -0700)
autoload/lsp/hover.vim
autoload/lsp/lsp.vim
autoload/lsp/lspserver.vim
autoload/lsp/signature.vim
autoload/lsp/util.vim
doc/lsp.txt
plugin/lsp.vim

index ab6ab8d7e523ac6ee222101547231b4af0bb155b..7119aab51a429f49459d68cb3bc9fcc63995165b 100644 (file)
@@ -7,50 +7,50 @@ import './options.vim' as opt
 
 # process the 'textDocument/hover' reply from the LSP server
 # Result: Hover | null
-export def HoverReply(lspserver: dict<any>, _: any, reply: dict<any>): void
-  if !util.SanitizeReply('textDocument/hover', reply)
+export def HoverReply(lspserver: dict<any>, hoverResult: any): void
+  if hoverResult->empty()
     return
   endif
 
   var hoverText: list<string>
   var hoverKind: string
 
-  if reply.result.contents->type() == v:t_dict
-    if reply.result.contents->has_key('kind')
+  if hoverResult.contents->type() == v:t_dict
+    if hoverResult.contents->has_key('kind')
       # MarkupContent
-      if reply.result.contents.kind == 'plaintext'
-        hoverText = reply.result.contents.value->split("\n")
+      if hoverResult.contents.kind == 'plaintext'
+        hoverText = hoverResult.contents.value->split("\n")
         hoverKind = 'text'
-      elseif reply.result.contents.kind == 'markdown'
-        hoverText = reply.result.contents.value->split("\n")
+      elseif hoverResult.contents.kind == 'markdown'
+        hoverText = hoverResult.contents.value->split("\n")
         hoverKind = 'markdown'
       else
-        util.ErrMsg($'Error: Unsupported hover contents type ({reply.result.contents.kind})')
+        util.ErrMsg($'Error: Unsupported hover contents type ({hoverResult.contents.kind})')
         return
       endif
-    elseif reply.result.contents->has_key('value')
+    elseif hoverResult.contents->has_key('value')
       # MarkedString
-      hoverText = reply.result.contents.value->split("\n")
+      hoverText = hoverResult.contents.value->split("\n")
     else
-      util.ErrMsg($'Error: Unsupported hover contents ({reply.result.contents})')
+      util.ErrMsg($'Error: Unsupported hover contents ({hoverResult.contents})')
       return
     endif
-  elseif reply.result.contents->type() == v:t_list
+  elseif hoverResult.contents->type() == v:t_list
     # interface MarkedString[]
-    for e in reply.result.contents
+    for e in hoverResult.contents
       if e->type() == v:t_string
         hoverText->extend(e->split("\n"))
       else
         hoverText->extend(e.value->split("\n"))
       endif
     endfor
-  elseif reply.result.contents->type() == v:t_string
-    if reply.result.contents->empty()
+  elseif hoverResult.contents->type() == v:t_string
+    if hoverResult.contents->empty()
       return
     endif
-    hoverText->extend(reply.result.contents->split("\n"))
+    hoverText->extend(hoverResult.contents->split("\n"))
   else
-    util.ErrMsg($'Error: Unsupported hover contents ({reply.result.contents})')
+    util.ErrMsg($'Error: Unsupported hover contents ({hoverResult.contents})')
     return
   endif
 
index 23ae46a7aa2181279af9141b41e518fae8d1c801..373ff050e6298dcaf713b1c7881f68df2b70cb4d 100644 (file)
@@ -92,9 +92,19 @@ def LspOmniComplSet(ftype: string, enabled: bool)
   ftypeOmniCtrlMap->extend({[ftype]: enabled})
 enddef
 
-export def EnableServerTrace()
-  util.ClearTraceLogs()
-  util.ServerTrace(true)
+# Enable/disable the logging of the language server protocol messages
+export def ServerDebug(arg: string)
+  if arg !=? 'on' && arg !=? 'off'
+    util.ErrMsg($'Error: Invalid argument ("{arg}") for LSP server debug')
+    return
+  endif
+
+  if arg ==? 'on'
+    util.ClearTraceLogs()
+    util.ServerTrace(true)
+  else
+    util.ServerTrace(false)
+  endif
 enddef
 
 # Show information about all the LSP servers
@@ -491,7 +501,7 @@ enddef
 
 # set the LSP server trace level for the current buffer
 # Params: SetTraceParams
-export def SetTraceServer(traceVal: string)
+export def ServerTraceSet(traceVal: string)
   if ['off', 'messages', 'verbose']->index(traceVal) == -1
     util.ErrMsg($'Error: Unsupported LSP server trace value {traceVal}')
     return
index 0f8287851544fa3f3dd3ad97d5a5295fe7ac5a18..6ef13f63d0685cc40d8c73d6366b5209b0f2e846 100644 (file)
@@ -17,7 +17,7 @@ import './callhierarchy.vim' as callhier
 
 # LSP server standard output handler
 def Output_cb(lspserver: dict<any>, chan: channel, msg: any): void
-  util.TraceLog(false, $'Received: {msg->string()}')
+  util.TraceLog(false, $'Received [{strftime("%m/%d/%y %T")}]: {msg->string()}')
   lspserver.data = msg
   lspserver.processMessages()
 enddef
@@ -99,7 +99,7 @@ def InitServer(lspserver: dict<any>)
        completionItem: {
          documentationFormat: ['plaintext', 'markdown'],
          resolveSupport: {properties: ['detail', 'documentation']},
-         snippetSupport: true
+         snippetSupport: false
        },
        completionItemKind: {valueSet: range(1, 25)}
       },
@@ -265,7 +265,7 @@ def SendMessage(lspserver: dict<any>, content: dict<any>): void
   endif
   ch->ch_sendexpr(content)
   if content->has_key('id')
-    util.TraceLog(false, $'Sent: {content->string()}')
+    util.TraceLog(false, $'Sent [{strftime("%m/%d/%y %T")}]: {content->string()}')
   endif
 enddef
 
@@ -283,8 +283,13 @@ def Rpc(lspserver: dict<any>, method: string, params: any): dict<any>
     return {}
   endif
 
+  util.TraceLog(false, $'Sent [{strftime("%m/%d/%y %T")}]: {req->string()}')
+
+  # Do the synchronous RPC call
   var reply = ch->ch_evalexpr(req)
 
+  util.TraceLog(false, $'Received [{strftime("%m/%d/%y %T")}]: {reply->string()}')
+
   if reply->has_key('result')
     # successful reply
     return reply
@@ -303,7 +308,31 @@ def Rpc(lspserver: dict<any>, method: string, params: any): dict<any>
   return {}
 enddef
 
+# LSP server asynchronous RPC callback
+def AsyncRpcCb(lspserver: dict<any>, method: string, RpcCb: func, chan: channel, reply: dict<any>)
+  util.TraceLog(false, $'Received [{strftime("%m/%d/%y %T")}]: {reply->string()}')
+
+  if reply->empty()
+    return
+  endif
+
+  if reply->has_key('error')
+    # request failed
+    var emsg: string
+    emsg = $'{reply.error.message}, code = {reply.error.code}'
+    if reply.error->has_key('data')
+      emsg ..= $', data = {reply.error.data->string()}'
+    endif
+    util.ErrMsg($'Error(LSP): request {method} failed ({emsg})')
+    return
+  endif
+
+  RpcCb(lspserver, reply.result)
+enddef
+
 # Send a async RPC request message to the LSP server with a callback function.
+# Returns the LSP message id.  This id can be used to cancel the RPC request
+# (if needed).  Returns -1 on error.
 def AsyncRpc(lspserver: dict<any>, method: string, params: any, Cbfunc: func): number
   var req = {}
   req.method = method
@@ -316,7 +345,20 @@ def AsyncRpc(lspserver: dict<any>, method: string, params: any, Cbfunc: func): n
     return -1
   endif
 
-  var reply = ch->ch_sendexpr(req, {callback: Cbfunc})
+  util.TraceLog(false, $'Sent [{strftime("%m/%d/%y %T")}]: {req->string()}')
+
+  # Do the asynchronous RPC call
+  var Fn = function('AsyncRpcCb', [lspserver, method, Cbfunc])
+
+  var reply: dict<any>
+  if get(g:, 'LSPTest')
+    # When running LSP tests, make this a synchronous RPC call
+    reply = Rpc(lspserver, method, params)
+    Fn(test_null_channel(), reply)
+  else
+    # Otherwise, make an asynchronous RPC call
+    reply = ch->ch_sendexpr(req, {callback: Fn})
+  endif
   if reply->empty()
     return -1
   endif
@@ -643,14 +685,8 @@ def ShowSignature(lspserver: dict<any>): void
   # interface SignatureHelpParams
   #   interface TextDocumentPositionParams
   var params = GetLspTextDocPosition()
-  if get(g:, 'LSPTest')
-    # When running LSP tests, make this a synchronous call
-    var reply = lspserver.rpc('textDocument/signatureHelp', params)
-    signature.SignatureHelp(lspserver, 0, reply)
-  else
-    lspserver.rpc_a('textDocument/signatureHelp', params,
-                   function(signature.SignatureHelp, [lspserver]))
-  endif
+  lspserver.rpc_a('textDocument/signatureHelp', params,
+                       signature.SignatureHelp)
 enddef
 
 def DidSaveFile(lspserver: dict<any>, bnr: number): void
@@ -682,14 +718,7 @@ def ShowHoverInfo(lspserver: dict<any>): void
   # interface HoverParams
   #   interface TextDocumentPositionParams
   var params = GetLspTextDocPosition()
-  if get(g:, 'LSPTest')
-    # When running LSP tests, make this a synchronous call
-    var reply = lspserver.rpc('textDocument/hover', params)
-    hover.HoverReply(lspserver, 0, reply)
-  else
-    lspserver.rpc_a('textDocument/hover', params,
-                   function(hover.HoverReply, [lspserver]))
-  endif
+  lspserver.rpc_a('textDocument/hover', params, hover.HoverReply)
 enddef
 
 # Request: "textDocument/references"
index 9acecb861a8ded462674552835b8899b10af73aa..c5c0c84a4a67060f05934a27b6e3eccfb7e54c30 100644 (file)
@@ -41,12 +41,7 @@ enddef
 # process the 'textDocument/signatureHelp' reply from the LSP server and
 # display the symbol signature help.
 # Result: SignatureHelp | null
-export def SignatureHelp(lspserver: dict<any>, _: any, reply: dict<any>): void
-  if !util.SanitizeReply('textDocument/signatureHelp', reply)
-    return
-  endif
-
-  var sighelp: dict<any> = reply.result
+export def SignatureHelp(lspserver: dict<any>, sighelp: any): void
   if sighelp->empty()
     CloseSignaturePopup(lspserver)
     return
index a567cbce4ab96a734c3e2d389b8e943fac5df8c2..25701e38bcb7c3a254dd3e31ac1dc702d39dde69 100644 (file)
@@ -35,9 +35,9 @@ export def TraceLog(stderr: bool, msg: string)
     return
   endif
   if stderr
-    writefile(split(msg, "\n"), $'{lsp_log_dir}lsp_server.err', 'a')
+    writefile(msg->split("\n"), $'{lsp_log_dir}lsp_server.err', 'a')
   else
-    writefile(split(msg, "\n"), $'{lsp_log_dir}lsp_server.out', 'a')
+    writefile([msg], $'{lsp_log_dir}lsp_server.out', 'a')
   endif
 enddef
 
@@ -151,27 +151,4 @@ export def PushCursorToTagStack()
                         }]}, 't')
 enddef
 
-export def SanitizeReply(reqmsg: string, reply: dict<any>): bool
-  if reply->empty()
-    return false
-  endif
-
-  if reply->has_key('error')
-    # request failed
-    var emsg: string
-    emsg = $'{reply.error.message}, code = {reply.error.code}'
-    if reply.error->has_key('data')
-      emsg ..= $', data = {reply.error.data->string()}'
-    endif
-    ErrMsg($'Error(LSP): request {reqmsg} failed ({emsg})')
-    return false
-  endif
-
-  if reply.result->empty()
-    return false
-  endif
-
-  return true
-enddef
-
 # vim: tabstop=8 shiftwidth=2 softtabstop=2
index c8379644a9181432f1e1e7493bf4b50c018236c5..71bbdc6b67a87a7ecd54239865b9c5ee88a87aac 100644 (file)
@@ -711,4 +711,36 @@ LspDiagsUpdated                    A |User| autocommand invoked when new
                                server.  This is invoked after the LSP client
                                has processed the diagnostics.
 
+==============================================================================
+10. Debugging                                          *lsp-debug*
+
+To debug this plugin, you can log the language server protocol messages sent
+and received by the plugin from the language server.  The following command
+enables the logging of the messages: >
+
+    :LspServerDebug on
+<
+This command also clears the log files.  The following command disables the
+logging of the messages: >
+
+    :LspServerDebug off
+<
+By default, the messages are not logged.
+
+The messages printed by the LSP server in the stdout are logged to the
+lsp_server.out file and the messages printed in the stderr are logged to the
+lsp_server.err file.  On a Unix-like system, these files are created in the
+/tmp directory.  On MS-Windows, these files are created in the %TEMP%
+directory.
+
+The language servers typically support command line options to enable debug
+messages and to increase the verbosity of the messages.  You can refer to the
+language server documentation for information about this.  You can include
+these options when registering the LSP server with this plugin.
+
+If a language server supports the "$/logTrace" LSP notification, then you can
+use the :LspServerTrace command to set the trace value: >
+
+    :LspServerTrace { off | messages | verbose }
+<
 vim:tw=78:ts=8:noet:ft=help:norl:
index 635328cd72260813a5f229edaf3b7656fe7bc7a8..c9a15a7c29661c1db71e8b79319d6a713dcfa01b 100644 (file)
@@ -14,10 +14,6 @@ def g:LspOptionsSet(opts: dict<any>)
   options.OptionsSet(opts)
 enddef
 
-def g:LspServerTraceEnable()
-  lsp.EnableServerTrace()
-enddef
-
 def g:LspAddServer(serverList: list<dict<any>>)
   lsp.AddServer(serverList)
 enddef
@@ -40,6 +36,16 @@ def LspServerTraceComplete(arglead: string, cmdline: string, cursorpos: number):
   endif
 enddef
 
+# Command line completion function for the LspSetTrace command.
+def LspServerDebugComplete(arglead: string, cmdline: string, cursorpos: number): list<string>
+  var l = ['off', 'on']
+  if arglead->empty()
+    return l
+  else
+    return filter(l, (_, val) => val =~ arglead)
+  endif
+enddef
+
 augroup LSPAutoCmds
   au!
   autocmd BufNewFile,BufReadPost * lsp.AddFile(expand('<abuf>')->str2nr())
@@ -59,7 +65,8 @@ augroup END
 command! -nargs=0 -bar LspShowServers lsp.ShowServers()
 command! -nargs=0 -bar LspShowServerCapabilities lsp.ShowServerCapabilities()
 command! -nargs=0 -bar LspServerRestart lsp.RestartServer()
-command! -nargs=1 -complete=customlist,LspServerTraceComplete -bar LspSetTrace lsp.SetTraceServer(<q-args>)
+command! -nargs=1 -complete=customlist,LspServerTraceComplete -bar LspServerTrace lsp.ServerTraceSet(<q-args>)
+command! -nargs=1 -complete=customlist,LspServerDebugComplete -bar LspServerDebug lsp.ServerDebug(<q-args>)
 command! -nargs=0 -bar LspGotoDefinition lsp.GotoDefinition(v:false)
 command! -nargs=0 -bar LspGotoDeclaration lsp.GotoDeclaration(v:false)
 command! -nargs=0 -bar LspGotoTypeDef lsp.GotoTypedef(v:false)