]> Sergey Matveev's repositories - vim-lsp.git/commitdiff
Use the lsp channel mode to simplify the code
authorYegappan Lakshmanan <yegappan@yahoo.com>
Thu, 6 Oct 2022 03:39:16 +0000 (20:39 -0700)
committerYegappan Lakshmanan <yegappan@yahoo.com>
Thu, 6 Oct 2022 03:39:16 +0000 (20:39 -0700)
autoload/lsp/handlers.vim
autoload/lsp/lspserver.vim

index 50dac81769438a8b991b55c3b058bb77ea2830fa..b6df9038b41ddaa80e7762e2fdc789e4d6fe1b6d 100644 (file)
@@ -839,81 +839,35 @@ export def ProcessMessages(lspserver: dict<any>): void
   var msg: dict<any>
   var req: dict<any>
 
-  while lspserver.data->len() > 0
-    idx = stridx(lspserver.data, 'Content-Length: ')
-    if idx == -1
-      return
-    endif
-
-    if stridx(lspserver.data, "\r\n", idx + 16) == -1
-      # not enough data is received. Wait for more data to arrive
-      return
-    endif
-
-    len = str2nr(lspserver.data[idx + 16 : ])
-    if len == 0
-      util.ErrMsg("Error(LSP): Invalid content length")
-      # Discard the header
-      lspserver.data = lspserver.data[idx + 16 :]
-      return
-    endif
-
-    # Header and contents are separated by '\r\n\r\n'
-    idx = stridx(lspserver.data, "\r\n\r\n", idx + 16)
-    if idx == -1
-      # content separator is not found. Wait for more data to arrive.
-      return
-    endif
-
-    # skip the separator
-    idx = idx + 4
-
-    if lspserver.data->len() - idx < len
-      # message is not fully received. Process the message after more data is
-      # received
-      return
-    endif
-
-    content = lspserver.data[idx : idx + len - 1]
-    try
-      msg = content->json_decode()
-    catch
-      util.ErrMsg($'Error(LSP): Malformed content ({content})')
-      lspserver.data = lspserver.data[idx + len :]
-      continue
-    endtry
-
-    if msg->has_key('result') || msg->has_key('error')
-      # response message from the server
-      req = lspserver.requests->get(msg.id->string(), {})
-      if !req->empty()
-       # Remove the corresponding stored request message
-       lspserver.requests->remove(msg.id->string())
-
-       if msg->has_key('result')
-         lspserver.processReply(req, msg)
-       else
-         # request failed
-         var emsg: string = msg.error.message
-         emsg ..= $', code = {msg.error.code}'
-         if msg.error->has_key('data')
-           emsg = $'{emsg}, data = {msg.error.data->string()}'
-         endif
-         util.ErrMsg($'Error(LSP): request {req.method} failed ({emsg})')
+  msg = lspserver.data
+  if msg->has_key('result') || msg->has_key('error')
+    # response message from the server
+    req = lspserver.requests->get(msg.id->string(), {})
+    if !req->empty()
+      # Remove the corresponding stored request message
+      lspserver.requests->remove(msg.id->string())
+
+      if msg->has_key('result')
+       lspserver.processReply(req, msg)
+      else
+       # request failed
+       var emsg: string = msg.error.message
+       emsg ..= ', code = ' .. msg.error.code
+       if msg.error->has_key('data')
+         emsg = emsg .. ', data = ' .. msg.error.data->string()
        endif
+       util.ErrMsg($'Error(LSP): request {req.method} failed ({emsg})')
       endif
-    elseif msg->has_key('id') && msg->has_key('method')
-      # request message from the server
-      lspserver.processRequest(msg)
-    elseif msg->has_key('method')
-      # notification message from the server
-      lspserver.processNotif(msg)
-    else
-      util.ErrMsg($'Error(LSP): Unsupported message ({msg->string()})')
     endif
-
-    lspserver.data = lspserver.data[idx + len :]
-  endwhile
+  elseif msg->has_key('id') && msg->has_key('method')
+    # request message from the server
+    lspserver.processRequest(msg)
+  elseif msg->has_key('method')
+    # notification message from the server
+    lspserver.processNotif(msg)
+  else
+    util.ErrMsg($'Error(LSP): Unsupported message ({msg->string()})')
+  endif
 enddef
 
 # vim: shiftwidth=2 softtabstop=2
index 5d32d867c4cd505e6f6994e1c8f095d3713f0562..9b4b416b32d59b26b53c0df3a167ec5478b42f87 100644 (file)
@@ -10,9 +10,9 @@ import './diag.vim'
 import './selection.vim'
 
 # LSP server standard output handler
-def Output_cb(lspserver: dict<any>, chan: channel, msg: string): void
-  util.TraceLog(false, msg)
-  lspserver.data = lspserver.data .. msg
+def Output_cb(lspserver: dict<any>, chan: channel, msg: any): void
+  util.TraceLog(false, msg->string())
+  lspserver.data = msg
   lspserver.processMessages()
 enddef
 
@@ -40,8 +40,8 @@ def StartServer(lspserver: dict<any>): number
   var cmd = [lspserver.path]
   cmd->extend(lspserver.args)
 
-  var opts = {in_mode: 'raw',
-               out_mode: 'raw',
+  var opts = {in_mode: 'lsp',
+               out_mode: 'lsp',
                err_mode: 'raw',
                noblock: 1,
                out_cb: function(Output_cb, [lspserver]),
@@ -251,15 +251,27 @@ enddef
 
 # Send a request message to LSP server
 def SendMessage(lspserver: dict<any>, content: dict<any>): void
-  var payload_js: string = content->json_encode()
-  var msg = $"Content-Length: {payload_js->len()}\r\n\r\n"
   var ch = lspserver.job->job_getchannel()
   if ch_status(ch) != 'open'
     # LSP server has exited
     return
   endif
-  ch->ch_sendraw(msg)
-  ch->ch_sendraw(payload_js)
+  ch->ch_sendexpr(content)
+enddef
+
+# Send a RPC request message to LSP server
+def RpcCall(lspserver: dict<any>, method: string, params: any): dict<any>
+  var req = {}
+  req.method = method
+  req.params = {}
+  req.params->extend(params)
+
+  var ch = lspserver.job->job_getchannel()
+  if ch_status(ch) != 'open'
+    # LSP server has exited
+    return {}
+  endif
+  return ch->ch_evalexpr(req)
 enddef
 
 # Wait for a response message from the LSP server for the request "req"
@@ -1010,6 +1022,7 @@ export def NewLspServer(path: string, args: list<string>, isSync: bool, initiali
     createNotification: function(CreateNotification, [lspserver]),
     sendResponse: function(SendResponse, [lspserver]),
     sendMessage: function(SendMessage, [lspserver]),
+    rpc: function(RpcCall, [lspserver]),
     waitForResponse: function(WaitForResponse, [lspserver]),
     processReply: function(handlers.ProcessReply, [lspserver]),
     processNotif: function(handlers.ProcessNotif, [lspserver]),