From 031088fc0afffe4af6fa90d68d5b93ca09992ef1 Mon Sep 17 00:00:00 2001 From: Michal Liszcz Date: Fri, 22 Dec 2023 15:03:13 +0100 Subject: [PATCH] fix(lsp): filetype matching to documentSelector in dynamic capabilities (#25425) Use the get_language_id client option to resolve the filetype when matching the document selector in a dynamic capability. Co-authored-by: Mathias Fussenegger --- runtime/lua/vim/lsp.lua | 2 +- runtime/lua/vim/lsp/_dynamic.lua | 16 ++++++++++------ test/functional/plugin/lsp_spec.lua | 21 +++++++++++++++++++-- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index 6476335213..ca7222a8f3 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1073,7 +1073,7 @@ function lsp.start_client(config) end --- @param method string - --- @param opts? {bufnr?: number} + --- @param opts? {bufnr: integer?} client.supports_method = function(method, opts) opts = opts or {} local required_capability = lsp._request_name_to_capability[method] diff --git a/runtime/lua/vim/lsp/_dynamic.lua b/runtime/lua/vim/lsp/_dynamic.lua index 4bee58559f..5edb27b498 100644 --- a/runtime/lua/vim/lsp/_dynamic.lua +++ b/runtime/lua/vim/lsp/_dynamic.lua @@ -55,7 +55,7 @@ function M:unregister(unregisterations) end --- @param method string ---- @param opts? {bufnr?: number} +--- @param opts? {bufnr: integer?} --- @return lsp.Registration? (table|nil) the registration if found --- @private function M:get(method, opts) @@ -69,14 +69,14 @@ function M:get(method, opts) if not documentSelector then return reg end - if M.match(opts.bufnr, documentSelector) then + if self:match(opts.bufnr, documentSelector) then return reg end end end --- @param method string ---- @param opts? {bufnr?: number} +--- @param opts? {bufnr: integer?} --- @private function M:supports(method, opts) return self:get(method, opts) ~= nil @@ -85,13 +85,17 @@ end --- @param bufnr number --- @param documentSelector lsp.DocumentSelector --- @private -function M.match(bufnr, documentSelector) - local ft = vim.bo[bufnr].filetype +function M:match(bufnr, documentSelector) + local client = vim.lsp.get_client_by_id(self.client_id) + if not client then + return false + end + local language = client.config.get_language_id(bufnr, vim.bo[bufnr].filetype) local uri = vim.uri_from_bufnr(bufnr) local fname = vim.uri_to_fname(uri) for _, filter in ipairs(documentSelector) do local matches = true - if filter.language and ft ~= filter.language then + if filter.language and language ~= filter.language then matches = false end if matches and filter.scheme and not vim.startswith(uri, filter.scheme .. ':') then diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua index 56d31a0e44..0026a7caa7 100644 --- a/test/functional/plugin/lsp_spec.lua +++ b/test/functional/plugin/lsp_spec.lua @@ -3936,12 +3936,15 @@ describe('LSP', function() describe('#dynamic vim.lsp._dynamic', function() it('supports dynamic registration', function() + ---@type string local root_dir = helpers.tmpname() os.remove(root_dir) mkdir(root_dir) local tmpfile = root_dir .. '/dynamic.foo' local file = io.open(tmpfile, 'w') - file:close() + if file then + file:close() + end exec_lua(create_server_definition) local result = exec_lua([[ @@ -3952,6 +3955,9 @@ describe('LSP', function() name = 'dynamic-test', cmd = server.cmd, root_dir = root_dir, + get_language_id = function() + return "dummy-lang" + end, capabilities = { textDocument = { formatting = { @@ -3985,6 +3991,13 @@ describe('LSP', function() { id = 'range-formatting', method = 'textDocument/rangeFormatting', + registerOptions = { + documentSelector = { + { + language = "dummy-lang" + }, + } + } }, }, }, { client_id = client_id }) @@ -4002,7 +4015,11 @@ describe('LSP', function() local function check(method, fname) local bufnr = fname and vim.fn.bufadd(fname) or nil local client = vim.lsp.get_client_by_id(client_id) - result[#result + 1] = {method = method, fname = fname, supported = client.supports_method(method, {bufnr = bufnr})} + result[#result + 1] = { + method = method, + fname = fname, + supported = client.supports_method(method, {bufnr = bufnr}) + } end