diff options
author | Mathias Fußenegger <mfussenegger@users.noreply.github.com> | 2022-09-20 09:28:23 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-20 09:28:23 +0200 |
commit | 10196f1b462400b8a4a9e8f13893da2514f8c850 (patch) | |
tree | c0a2f483aa487cc2bc4ca2032a0dca2bfba3d569 | |
parent | a0e6e767a617d79983ac4982850dee6d95ed5b56 (diff) | |
download | rneovim-10196f1b462400b8a4a9e8f13893da2514f8c850.tar.gz rneovim-10196f1b462400b8a4a9e8f13893da2514f8c850.tar.bz2 rneovim-10196f1b462400b8a4a9e8f13893da2514f8c850.zip |
fix(lsp): support `false` result in handlers (#20252)
Closes https://github.com/neovim/neovim/issues/20111
-rw-r--r-- | runtime/lua/vim/lsp/rpc.lua | 3 | ||||
-rw-r--r-- | test/functional/plugin/lsp_spec.lua | 71 |
2 files changed, 72 insertions, 2 deletions
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 7d047f8958..755c0ffc6f 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -405,8 +405,7 @@ function Client:handle_body(body) { status = status, result = result, err = err } ) if status then - if not (result or err) then - -- TODO this can be a problem if `null` is sent for result. needs vim.NIL + if result == nil and err == nil then error( string.format( 'method %q: either a result or an error must be sent to the server in response', diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 395f8ed32a..e7ea089fbf 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -3292,4 +3292,75 @@ describe('LSP', function() eq(result.method, "initialize") end) end) + + describe('handlers', function() + it('handler can return false as response', function() + local result = exec_lua [[ + local uv = vim.loop + local server = uv.new_tcp() + local messages = {} + local responses = {} + server:bind('127.0.0.1', 0) + server:listen(127, function(err) + assert(not err, err) + local socket = uv.new_tcp() + server:accept(socket) + socket:read_start(require('vim.lsp.rpc').create_read_loop(function(body) + local payload = vim.json.decode(body) + if payload.method then + table.insert(messages, payload.method) + if payload.method == 'initialize' then + local msg = vim.json.encode({ + id = payload.id, + jsonrpc = '2.0', + result = { + capabilities = {} + }, + }) + socket:write(table.concat({'Content-Length: ', tostring(#msg), '\r\n\r\n', msg})) + elseif payload.method == 'initialized' then + local msg = vim.json.encode({ + id = 10, + jsonrpc = '2.0', + method = 'dummy', + params = {}, + }) + socket:write(table.concat({'Content-Length: ', tostring(#msg), '\r\n\r\n', msg})) + end + else + table.insert(responses, payload) + socket:close() + end + end)) + end) + local port = server:getsockname().port + local handler_called = false + vim.lsp.handlers['dummy'] = function(err, result) + handler_called = true + return false + end + local client_id = vim.lsp.start({ name = 'dummy', cmd = vim.lsp.rpc.connect('127.0.0.1', port) }) + local client = vim.lsp.get_client_by_id(client_id) + vim.wait(1000, function() return #messages == 2 and handler_called and #responses == 1 end) + server:close() + server:shutdown() + return { + messages = messages, + handler_called = handler_called, + responses = responses } + ]] + local expected = { + messages = { 'initialize', 'initialized' }, + handler_called = true, + responses = { + { + id = 10, + jsonrpc = '2.0', + result = false + } + } + } + eq(expected, result) + end) + end) end) |