From: Yegappan Lakshmanan Date: Thu, 6 Oct 2022 03:39:16 +0000 (-0700) Subject: Use the lsp channel mode to simplify the code X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=5d81b0d2c51fa6702879f87571b0b53b974e384c;p=vim-lsp.git Use the lsp channel mode to simplify the code --- diff --git a/autoload/lsp/handlers.vim b/autoload/lsp/handlers.vim index 50dac81..b6df903 100644 --- a/autoload/lsp/handlers.vim +++ b/autoload/lsp/handlers.vim @@ -839,81 +839,35 @@ export def ProcessMessages(lspserver: dict): void var msg: dict var req: dict - 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 diff --git a/autoload/lsp/lspserver.vim b/autoload/lsp/lspserver.vim index 5d32d86..9b4b416 100644 --- a/autoload/lsp/lspserver.vim +++ b/autoload/lsp/lspserver.vim @@ -10,9 +10,9 @@ import './diag.vim' import './selection.vim' # LSP server standard output handler -def Output_cb(lspserver: dict, chan: channel, msg: string): void - util.TraceLog(false, msg) - lspserver.data = lspserver.data .. msg +def Output_cb(lspserver: dict, chan: channel, msg: any): void + util.TraceLog(false, msg->string()) + lspserver.data = msg lspserver.processMessages() enddef @@ -40,8 +40,8 @@ def StartServer(lspserver: dict): 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, content: dict): 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, method: string, params: any): dict + 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, 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]),