fix(lsp): do not assume client capability exists in watchfiles check (#24558)

Backports #24550.

Adjusts test to expect that didChangeWatchedFiles is *not* registered if
client `capabilities` is nil (as it's not enabled by default for v0.9).
This commit is contained in:
Sean Dewar
2023-08-04 10:16:54 +01:00
committed by GitHub
parent 5e6c8b3385
commit df63474930
4 changed files with 71 additions and 49 deletions

View File

@@ -974,8 +974,7 @@ start_client({config}) *vim.lsp.start_client()*
passed to the language server on initialization. Hint: use passed to the language server on initialization. Hint: use
make_client_capabilities() and modify its result. make_client_capabilities() and modify its result.
• Note: To send an empty dictionary use • Note: To send an empty dictionary use
`{[vim.type_idx]=vim.types.dictionary}`, else it will be |vim.empty_dict()|, else it will be encoded as an array.
encoded as an array.
• handlers: Map of language server method names to • handlers: Map of language server method names to
|lsp-handler| |lsp-handler|

View File

@@ -933,8 +933,7 @@ end
--- |vim.lsp.protocol.make_client_capabilities()|, passed to the language --- |vim.lsp.protocol.make_client_capabilities()|, passed to the language
--- server on initialization. Hint: use make_client_capabilities() and modify --- server on initialization. Hint: use make_client_capabilities() and modify
--- its result. --- its result.
--- - Note: To send an empty dictionary use --- - Note: To send an empty dictionary use |vim.empty_dict()|, else it will be encoded as an
--- `{[vim.type_idx]=vim.types.dictionary}`, else it will be encoded as an
--- array. --- array.
--- ---
--- - handlers: Map of language server method names to |lsp-handler| --- - handlers: Map of language server method names to |lsp-handler|

View File

@@ -193,12 +193,15 @@ local to_lsp_change_type = {
function M.register(reg, ctx) function M.register(reg, ctx)
local client_id = ctx.client_id local client_id = ctx.client_id
local client = vim.lsp.get_client_by_id(client_id) local client = vim.lsp.get_client_by_id(client_id)
if
-- Ill-behaved servers may not honor the client capability and try to register -- Ill-behaved servers may not honor the client capability and try to register
-- anyway, so ignore requests when the user has opted out of the feature. -- anyway, so ignore requests when the user has opted out of the feature.
not client.config.capabilities.workspace.didChangeWatchedFiles.dynamicRegistration local has_capability = vim.tbl_get(
or not client.workspace_folders client.config.capabilities or {},
then 'workspace',
'didChangeWatchedFiles',
'dynamicRegistration'
)
if not has_capability or not client.workspace_folders then
return return
end end
local watch_regs = {} local watch_regs = {}

View File

@@ -4217,27 +4217,26 @@ describe('LSP', function()
it("ignores registrations by servers when the client doesn't advertise support", function() it("ignores registrations by servers when the client doesn't advertise support", function()
exec_lua(create_server_definition) exec_lua(create_server_definition)
local result = exec_lua([[ exec_lua([[
local server = _create_server() server = _create_server()
local client_id = vim.lsp.start({
name = 'watchfiles-test',
cmd = server.cmd,
root_dir = 'some_dir',
capabilities = {
workspace = {
didChangeWatchedFiles = {
dynamicRegistration = false,
},
},
},
})
local watching = false
require('vim.lsp._watchfiles')._watchfunc = function(_, _, callback) require('vim.lsp._watchfiles')._watchfunc = function(_, _, callback)
-- Since the registration is ignored, this should not execute and `watching` should stay false -- Since the registration is ignored, this should not execute and `watching` should stay false
watching = true watching = true
return function() end return function() end
end end
]])
local function check_registered(capabilities)
return exec_lua([[
watching = false
local client_id = vim.lsp.start({
name = 'watchfiles-test',
cmd = server.cmd,
root_dir = 'some_dir',
capabilities = ...,
}, {
reuse_client = function() return false end,
})
vim.lsp.handlers['client/registerCapability'](nil, { vim.lsp.handlers['client/registerCapability'](nil, {
registrations = { registrations = {
@@ -4265,10 +4264,32 @@ describe('LSP', function()
}, },
}, { client_id = client_id }) }, { client_id = client_id })
vim.lsp.stop_client(client_id, true)
return watching return watching
]]) ]], capabilities)
end
eq(false, result) eq(false, check_registered(nil)) -- start{_client}() defaults to make_client_capabilities().
eq(false, check_registered(vim.empty_dict()))
eq(false, check_registered({
workspace = {
ignoreMe = true,
},
}))
eq(false, check_registered({
workspace = {
didChangeWatchedFiles = {
dynamicRegistration = false,
},
},
}))
eq(true, check_registered({
workspace = {
didChangeWatchedFiles = {
dynamicRegistration = true,
},
},
}))
end) end)
end) end)
end) end)