aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIlia Choly <ilia.choly@gmail.com>2024-05-23 09:17:53 -0400
committerGitHub <noreply@github.com>2024-05-23 15:17:53 +0200
commitaf200c10cf9d117a14ebf9f2e9c666721a1090d6 (patch)
tree96f4e94ed24dff6a0ddea56d2c19bf96731470cd
parent2908f71dc9e9591f97e0f9d70dbc8d8b18f9e475 (diff)
downloadrneovim-af200c10cf9d117a14ebf9f2e9c666721a1090d6.tar.gz
rneovim-af200c10cf9d117a14ebf9f2e9c666721a1090d6.tar.bz2
rneovim-af200c10cf9d117a14ebf9f2e9c666721a1090d6.zip
fix(lsp): check if buffer was detached in on_init callback (#28914)
Co-authored-by: Jongwook Choi <wookayin@gmail.com>
-rw-r--r--runtime/lua/vim/lsp/client.lua5
-rw-r--r--test/functional/plugin/lsp/inlay_hint_spec.lua12
-rw-r--r--test/functional/plugin/lsp/semantic_tokens_spec.lua34
-rw-r--r--test/functional/plugin/lsp/testutil.lua3
-rw-r--r--test/functional/plugin/lsp_spec.lua57
5 files changed, 71 insertions, 40 deletions
diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua
index 8fb5879e9b..4beb7fefda 100644
--- a/runtime/lua/vim/lsp/client.lua
+++ b/runtime/lua/vim/lsp/client.lua
@@ -612,7 +612,10 @@ function Client:initialize()
self:_run_callbacks(self._on_init_cbs, lsp.client_errors.ON_INIT_CALLBACK_ERROR, self, result)
for buf in pairs(reattach_bufs) do
- self:_on_attach(buf)
+ -- The buffer may have been detached in the on_init callback.
+ if self.attached_buffers[buf] then
+ self:_on_attach(buf)
+ end
end
log.info(
diff --git a/test/functional/plugin/lsp/inlay_hint_spec.lua b/test/functional/plugin/lsp/inlay_hint_spec.lua
index 3d0fcc31ff..d3b5ae0e4e 100644
--- a/test/functional/plugin/lsp/inlay_hint_spec.lua
+++ b/test/functional/plugin/lsp/inlay_hint_spec.lua
@@ -70,8 +70,8 @@ before_each(function()
inlayHintProvider = true,
},
handlers = {
- ['textDocument/inlayHint'] = function()
- return vim.json.decode(response)
+ ['textDocument/inlayHint'] = function(_, _, callback)
+ callback(nil, vim.json.decode(response))
end,
}
})
@@ -106,8 +106,8 @@ describe('vim.lsp.inlay_hint', function()
inlayHintProvider = true,
},
handlers = {
- ['textDocument/inlayHint'] = function()
- return {}
+ ['textDocument/inlayHint'] = function(_, _, callback)
+ callback(nil, {})
end,
}
})
@@ -206,8 +206,8 @@ describe('vim.lsp.inlay_hint', function()
inlayHintProvider = true,
},
handlers = {
- ['textDocument/inlayHint'] = function()
- return { expected2 }
+ ['textDocument/inlayHint'] = function(_, _, callback)
+ callback(nil, { expected2 })
end,
}
})
diff --git a/test/functional/plugin/lsp/semantic_tokens_spec.lua b/test/functional/plugin/lsp/semantic_tokens_spec.lua
index 60f02b0521..7908c5d2e7 100644
--- a/test/functional/plugin/lsp/semantic_tokens_spec.lua
+++ b/test/functional/plugin/lsp/semantic_tokens_spec.lua
@@ -95,11 +95,11 @@ describe('semantic token highlighting', function()
},
},
handlers = {
- ['textDocument/semanticTokens/full'] = function()
- return vim.fn.json_decode(response)
+ ['textDocument/semanticTokens/full'] = function(_, _, callback)
+ callback(nil, vim.fn.json_decode(response))
end,
- ['textDocument/semanticTokens/full/delta'] = function()
- return vim.fn.json_decode(edit_response)
+ ['textDocument/semanticTokens/full/delta'] = function(_, _, callback)
+ callback(nil, vim.fn.json_decode(edit_response))
end,
}
})
@@ -560,11 +560,11 @@ describe('semantic token highlighting', function()
},
},
handlers = {
- ['textDocument/semanticTokens/full'] = function()
- return nil
+ ['textDocument/semanticTokens/full'] = function(_, _, callback)
+ callback(nil, nil)
end,
['textDocument/semanticTokens/full/delta'] = function()
- return nil
+ callback(nil, nil)
end,
}
})
@@ -608,11 +608,11 @@ describe('semantic token highlighting', function()
},
},
handlers = {
- ['textDocument/semanticTokens/full'] = function()
- return vim.fn.json_decode(response)
+ ['textDocument/semanticTokens/full'] = function(_, _, callback)
+ callback(nil, vim.fn.json_decode(response))
end,
- ['textDocument/semanticTokens/full/delta'] = function()
- return vim.fn.json_decode(edit_response)
+ ['textDocument/semanticTokens/full/delta'] = function(_, _, callback)
+ callback(nil, vim.fn.json_decode(edit_response))
end,
}
})
@@ -1075,8 +1075,8 @@ b = "as"]],
},
},
handlers = {
- ['textDocument/semanticTokens/full'] = function()
- return vim.fn.json_decode(resp)
+ ['textDocument/semanticTokens/full'] = function(_, _, callback)
+ callback(nil, vim.fn.json_decode(resp))
end,
}
})
@@ -1461,11 +1461,11 @@ int main()
},
},
handlers = {
- ['textDocument/semanticTokens/full'] = function()
- return vim.fn.json_decode(resp1)
+ ['textDocument/semanticTokens/full'] = function(_, _, callback)
+ callback(nil, vim.fn.json_decode(resp1))
end,
- ['textDocument/semanticTokens/full/delta'] = function()
- return vim.fn.json_decode(resp2)
+ ['textDocument/semanticTokens/full/delta'] = function(_, _, callback)
+ callback(nil, vim.fn.json_decode(resp2))
end,
}
})
diff --git a/test/functional/plugin/lsp/testutil.lua b/test/functional/plugin/lsp/testutil.lua
index 4d14752f2a..3430a1e1a3 100644
--- a/test/functional/plugin/lsp/testutil.lua
+++ b/test/functional/plugin/lsp/testutil.lua
@@ -39,8 +39,7 @@ M.create_server_definition = [[
})
local handler = handlers[method]
if handler then
- local response, err = handler(method, params)
- callback(err, response)
+ handler(method, params, callback)
elseif method == 'initialize' then
callback(nil, {
capabilities = opts.capabilities or {}
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 8358a1b9ec..c95a96baca 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -501,6 +501,35 @@ describe('LSP', function()
eq(true, result.detach_called)
end)
+ it('should not re-attach buffer if it was deleted in on_init #28575', function()
+ clear()
+ exec_lua(create_server_definition)
+ exec_lua([[
+ local server = _create_server({
+ handlers = {
+ initialize = function(method, params, callback)
+ vim.schedule(function()
+ callback(nil, { capabilities = {} })
+ end)
+ end
+ }
+ })
+ local bufnr = vim.api.nvim_create_buf(false, true)
+ local on_init_called = false
+ local client_id = vim.lsp.start({
+ name = 'detach-dummy',
+ cmd = server.cmd,
+ on_init = function()
+ vim.api.nvim_buf_delete(bufnr, {})
+ on_init_called = true
+ end
+ })
+ vim.lsp.buf_attach_client(bufnr, client_id)
+ local ok = vim.wait(1000, function() return on_init_called end)
+ assert(ok, "on_init was not called")
+ ]])
+ end)
+
it('client should return settings via workspace/configuration handler', function()
local expected_handlers = {
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
@@ -670,7 +699,7 @@ describe('LSP', function()
}
},
handlers = {
- ['textDocument/willSaveWaitUntil'] = function()
+ ['textDocument/willSaveWaitUntil'] = function(_, _, callback)
local text_edit = {
range = {
start = { line = 0, character = 0 },
@@ -678,7 +707,7 @@ describe('LSP', function()
},
newText = 'Hello'
}
- return { text_edit, }
+ callback(nil, { text_edit, })
end
},
})
@@ -4144,8 +4173,8 @@ describe('LSP', function()
}
},
handlers = {
- ["textDocument/codeAction"] = function()
- return {
+ ["textDocument/codeAction"] = function(_, _, callback)
+ callback(nil, {
{
title = "Code Action 1",
command = {
@@ -4153,10 +4182,10 @@ describe('LSP', function()
command = "command:1",
}
}
- }
+ })
end,
- ["codeAction/resolve"] = function()
- return nil, "resolve failed"
+ ["codeAction/resolve"] = function(_, _, callback)
+ callback("resolve failed", nil)
end,
}
})
@@ -4344,7 +4373,7 @@ describe('LSP', function()
},
},
handlers = {
- ["textDocument/codeLens"] = function(method, params)
+ ["textDocument/codeLens"] = function(method, params, callback)
local lenses = {
{
range = {
@@ -4357,7 +4386,7 @@ describe('LSP', function()
},
},
}
- return lenses
+ callback(nil, lenses)
end,
}
})
@@ -4665,13 +4694,13 @@ describe('LSP', function()
},
handlers = {
---@return lsp.Location[]
- ['textDocument/definition'] = function()
- return { _G.mock_locations[1] }
+ ['textDocument/definition'] = function(_, _, callback)
+ callback(nil, { _G.mock_locations[1] })
end,
---@return lsp.WorkspaceSymbol[]
- ['workspace/symbol'] = function(_, request)
+ ['workspace/symbol'] = function(_, request, callback)
assert(request.query == 'foobar')
- return {
+ callback(nil, {
{
name = 'foobar',
kind = 13, ---@type lsp.SymbolKind
@@ -4682,7 +4711,7 @@ describe('LSP', function()
kind = 12, ---@type lsp.SymbolKind
location = _G.mock_locations[2],
}
- }
+ })
end,
},
})