fix(lsp): don't register didChangeWatchedFiles when capability not set (#23689)

Some LSP servers (tailwindcss, rome) are known to request registration
for `workspace/didChangeWatchedFiles` even when the corresponding client
capability does not advertise support. This change adds an extra check
in the `client/registerCapability` handler not to start a watch unless
the client capability is set appropriately.
This commit is contained in:
Jon Huhn 2023-05-20 00:45:39 -05:00 committed by GitHub
parent 413d57ae71
commit 073035a030
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 90 additions and 1 deletions

View File

@ -193,7 +193,12 @@ local to_lsp_change_type = {
function M.register(reg, ctx)
local client_id = ctx.client_id
local client = vim.lsp.get_client_by_id(client_id)
if not client.workspace_folders then
if
-- 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.
not client.config.capabilities.workspace.didChangeWatchedFiles.dynamicRegistration
or not client.workspace_folders
then
return
end
local watch_regs = {}

View File

@ -3778,6 +3778,13 @@ describe('LSP', function()
name = 'watchfiles-test',
cmd = server.cmd,
root_dir = root_dir,
capabilities = {
workspace = {
didChangeWatchedFiles = {
dynamicRegistration = true,
},
},
},
})
local expected_messages = 2 -- initialize, initialized
@ -3865,6 +3872,13 @@ describe('LSP', function()
name = 'watchfiles-test',
cmd = server.cmd,
root_dir = root_dir,
capabilities = {
workspace = {
didChangeWatchedFiles = {
dynamicRegistration = true,
},
},
},
})
local expected_messages = 2 -- initialize, initialized
@ -3982,6 +3996,13 @@ describe('LSP', function()
name = 'watchfiles-test',
cmd = server.cmd,
root_dir = root_dir,
capabilities = {
workspace = {
didChangeWatchedFiles = {
dynamicRegistration = true,
},
},
},
})
local expected_messages = 2 -- initialize, initialized
@ -4116,6 +4137,13 @@ describe('LSP', function()
name = 'watchfiles-test',
cmd = server.cmd,
root_dir = root_dir,
capabilities = {
workspace = {
didChangeWatchedFiles = {
dynamicRegistration = true,
},
},
},
})
local expected_messages = 2 -- initialize, initialized
@ -4186,5 +4214,61 @@ describe('LSP', function()
},
}, result[3].params)
end)
it("ignores registrations by servers when the client doesn't advertise support", function()
exec_lua(create_server_definition)
local result = exec_lua([[
local 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)
-- Since the registration is ignored, this should not execute and `watching` should stay false
watching = true
return function() end
end
vim.lsp.handlers['client/registerCapability'](nil, {
registrations = {
{
id = 'watchfiles-test-kind',
method = 'workspace/didChangeWatchedFiles',
registerOptions = {
watchers = {
{
globPattern = '**/*',
},
},
},
},
},
}, { client_id = client_id })
-- Ensure no errors occur when unregistering something that was never really registered.
vim.lsp.handlers['client/unregisterCapability'](nil, {
unregisterations = {
{
id = 'watchfiles-test-kind',
method = 'workspace/didChangeWatchedFiles',
},
},
}, { client_id = client_id })
return watching
]])
eq(false, result)
end)
end)
end)