diff options
Diffstat (limited to 'runtime/lua/vim/lsp/rpc.lua')
-rw-r--r-- | runtime/lua/vim/lsp/rpc.lua | 87 |
1 files changed, 8 insertions, 79 deletions
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 7f31bbdf75..d9a684a738 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -4,34 +4,6 @@ local log = require('vim.lsp.log') local protocol = require('vim.lsp.protocol') local validate, schedule, schedule_wrap = vim.validate, vim.schedule, vim.schedule_wrap --- TODO replace with a better implementation. ----@private ---- Encodes to JSON. ---- ----@param data (table) Data to encode ----@returns (string) Encoded object -local function json_encode(data) - local status, result = pcall(vim.fn.json_encode, data) - if status then - return result - else - return nil, result - end -end ----@private ---- Decodes from JSON. ---- ----@param data (string) Data to decode ----@returns (table) Decoded JSON object -local function json_decode(data) - local status, result = pcall(vim.fn.json_decode, data) - if status then - return result - else - return nil, result - end -end - ---@private --- Checks whether a given path exists and is a directory. ---@param filename (string) path to check @@ -41,36 +13,6 @@ local function is_dir(filename) return stat and stat.type == 'directory' or false end -local NIL = vim.NIL - ----@private -local recursive_convert_NIL -recursive_convert_NIL = function(v, tbl_processed) - if v == NIL then - return nil - elseif not tbl_processed[v] and type(v) == 'table' then - tbl_processed[v] = true - local inside_list = vim.tbl_islist(v) - return vim.tbl_map(function(x) - if not inside_list or (inside_list and type(x) == "table") then - return recursive_convert_NIL(x, tbl_processed) - else - return x - end - end, v) - end - - return v -end - ----@private ---- Returns its argument, but converts `vim.NIL` to Lua `nil`. ----@param v (any) Argument ----@returns (any) -local function convert_NIL(v) - return recursive_convert_NIL(v, {}) -end - ---@private --- Merges current process env with the given env and returns the result as --- a list of "k=v" strings. @@ -389,16 +331,13 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params) --- Encodes {payload} into a JSON-RPC message and sends it to the remote --- process. --- - ---@param payload (table) Converted into a JSON string, see |json_encode()| + ---@param payload table ---@returns true if the payload could be scheduled, false if the main event-loop is in the process of closing. local function encode_and_send(payload) local _ = log.debug() and log.debug("rpc.send", payload) if handle == nil or handle:is_closing() then return false end - -- TODO(ashkan) remove this once we have a Lua json_encode - schedule(function() - local encoded = assert(json_encode(payload)) - stdin:write(format_message_with_content_length(encoded)) - end) + local encoded = vim.json.encode(payload) + stdin:write(format_message_with_content_length(encoded)) return true end @@ -488,16 +427,15 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params) ---@private local function handle_body(body) - local decoded, err = json_decode(body) - if not decoded then - -- on_error(client_errors.INVALID_SERVER_JSON, err) + local ok, decoded = pcall(vim.json.decode, body, { luanil = { object = true } }) + if not ok then + on_error(client_errors.INVALID_SERVER_JSON, decoded) return end local _ = log.debug() and log.debug("rpc.receive", decoded) if type(decoded.method) == 'string' and decoded.id then - -- Server Request - decoded.params = convert_NIL(decoded.params) + local err -- Schedule here so that the users functions don't trigger an error and -- we can still use the result. schedule(function() @@ -524,22 +462,16 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params) end) -- This works because we are expecting vim.NIL here elseif decoded.id and (decoded.result ~= vim.NIL or decoded.error ~= vim.NIL) then - -- Server Result - decoded.error = convert_NIL(decoded.error) - decoded.result = convert_NIL(decoded.result) -- We sent a number, so we expect a number. local result_id = tonumber(decoded.id) - -- Do not surface RequestCancelled or ContentModified to users, it is RPC-internal. + -- Do not surface RequestCancelled to users, it is RPC-internal. if decoded.error then local mute_error = false if decoded.error.code == protocol.ErrorCodes.RequestCancelled then local _ = log.debug() and log.debug("Received cancellation ack", decoded) mute_error = true - elseif decoded.error.code == protocol.ErrorCodes.ContentModified then - local _ = log.debug() and log.debug("Received content modified ack", decoded) - mute_error = true end if mute_error then @@ -574,7 +506,6 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params) end elseif type(decoded.method) == 'string' then -- Notification - decoded.params = convert_NIL(decoded.params) try_call(client_errors.NOTIFICATION_HANDLER_ERROR, dispatchers.notification, decoded.method, decoded.params) else @@ -582,8 +513,6 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params) on_error(client_errors.INVALID_SERVER_MESSAGE, decoded) end end - -- TODO(ashkan) remove this once we have a Lua json_decode - handle_body = schedule_wrap(handle_body) local request_parser = coroutine.wrap(request_parser_loop) request_parser() |