neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit 10196f1b462400b8a4a9e8f13893da2514f8c850
parent a0e6e767a617d79983ac4982850dee6d95ed5b56
Author: Mathias Fußenegger <mfussenegger@users.noreply.github.com>
Date:   Tue, 20 Sep 2022 09:28:23 +0200

fix(lsp): support `false` result in handlers (#20252)

Closes https://github.com/neovim/neovim/issues/20111
Diffstat:
Mruntime/lua/vim/lsp/rpc.lua | 3+--
Mtest/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 @@ -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 @@ -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)