diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 4061b6c4df..54be43522b 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -2212,14 +2212,11 @@ enable({enable}, {bufnr}, {opts}) *vim.lsp.document_color.enable()* Enables document highlighting from the given language client in the given buffer. - You can enable document highlighting from a supporting client as follows: >lua + You can enable document highlighting when a client attaches to a buffer as + follows: >lua vim.api.nvim_create_autocmd('LspAttach', { callback = function(args) - local client = vim.lsp.get_client_by_id(args.data.client_id) - - if client:supports_method('textDocument/documentColor') then - vim.lsp.document_color.enable(true, args.buf) - end + vim.lsp.document_color.enable(true, args.buf) end }) < diff --git a/runtime/lua/vim/lsp/document_color.lua b/runtime/lua/vim/lsp/document_color.lua index 2084c8a465..c2b1f3c424 100644 --- a/runtime/lua/vim/lsp/document_color.lua +++ b/runtime/lua/vim/lsp/document_color.lua @@ -172,16 +172,6 @@ local function buf_clear(bufnr) api.nvim__redraw({ buf = bufnr, valid = true, flush = false }) end ---- @param bufnr integer ---- @param client_id? integer -local function buf_refresh(bufnr, client_id) - util._refresh(ms.textDocument_documentColor, { - bufnr = bufnr, - handler = on_document_color, - client_id = client_id, - }) -end - --- @param bufnr integer local function buf_disable(bufnr) buf_clear(bufnr) @@ -196,7 +186,7 @@ local function buf_enable(bufnr) on_reload = function(_, buf) buf_clear(buf) if bufstates[buf].enabled then - buf_refresh(buf) + M._buf_refresh(buf) end end, on_detach = function(_, buf) @@ -215,7 +205,7 @@ local function buf_enable(bufnr) (method == ms.textDocument_didChange or method == ms.textDocument_didOpen) and bufstates[args.buf].enabled then - buf_refresh(args.buf, args.data.client_id) + M._buf_refresh(args.buf, args.data.client_id) end end, }) @@ -238,7 +228,18 @@ local function buf_enable(bufnr) end, }) - buf_refresh(bufnr) + M._buf_refresh(bufnr) +end + +--- @nodoc +--- @param bufnr integer +--- @param client_id? integer +function M._buf_refresh(bufnr, client_id) + util._refresh(ms.textDocument_documentColor, { + bufnr = bufnr, + handler = on_document_color, + client_id = client_id, + }) end --- Query whether document colors are enabled in the given buffer. @@ -259,15 +260,11 @@ end --- Enables document highlighting from the given language client in the given buffer. --- ---- You can enable document highlighting from a supporting client as follows: +--- You can enable document highlighting when a client attaches to a buffer as follows: --- ```lua --- vim.api.nvim_create_autocmd('LspAttach', { --- callback = function(args) ---- local client = vim.lsp.get_client_by_id(args.data.client_id) ---- ---- if client:supports_method('textDocument/documentColor') then ---- vim.lsp.document_color.enable(true, args.buf) ---- end +--- vim.lsp.document_color.enable(true, args.buf) --- end --- }) --- ``` @@ -307,7 +304,7 @@ api.nvim_create_autocmd('ColorScheme', { for _, bufnr in ipairs(api.nvim_list_bufs()) do buf_clear(bufnr) if api.nvim_buf_is_loaded(bufnr) and bufstates[bufnr].enabled then - buf_refresh(bufnr) + M._buf_refresh(bufnr) else reset_bufstate(bufnr, false) end diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 2d27f4b07c..ed8affc038 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -128,6 +128,15 @@ RSC[ms.client_registerCapability] = function(_, params, ctx) for bufnr in pairs(client.attached_buffers) do vim.lsp._set_defaults(client, bufnr) end + for _, reg in ipairs(params.registrations) do + if reg.method == ms.textDocument_documentColor then + for bufnr in pairs(client.attached_buffers) do + if vim.lsp.document_color.is_enabled(bufnr) then + vim.lsp.document_color._buf_refresh(bufnr, client.id) + end + end + end + end return vim.NIL end diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index 50730b2971..f27b9dffef 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -533,7 +533,7 @@ function protocol.make_client_capabilities() dynamicRegistration = false, }, colorProvider = { - dynamicRegistration = false, + dynamicRegistration = true, }, }, workspace = { diff --git a/test/functional/plugin/lsp/document_color_spec.lua b/test/functional/plugin/lsp/document_color_spec.lua index a938d367d4..9c6d6a681e 100644 --- a/test/functional/plugin/lsp/document_color_spec.lua +++ b/test/functional/plugin/lsp/document_color_spec.lua @@ -115,6 +115,49 @@ body { screen:expect({ grid = grid_without_colors }) end) + it('supports dynamic registration', function() + local grid_with_dynamic_highlights = [[ + body { | + {2:color}: {2:#FFF}; | + background-color: {3:rgb(0, 255, 255)}; | + } | + ^ | + {1:~ }|*8 + | + ]] + + exec_lua(function() + _G.server2 = _G._create_server({ + colorProvider = { + documentSelector = nil, + }, + handlers = { + ['textDocument/documentColor'] = function(_, _, callback) + callback(nil, { + { + range = { + start = { line = 1, character = 2 }, + ['end'] = { line = 1, character = 7 }, + }, + color = { red = 1, green = 1, blue = 1 }, + }, + }) + end, + }, + }) + + local client_id2 = assert(vim.lsp.start({ name = 'dummy2', cmd = _G.server2.cmd })) + + vim.lsp.handlers['client/registerCapability'](nil, { + registrations = { + { id = 'documentColor', method = 'textDocument/documentColor' }, + }, + }, { client_id = client_id2, method = 'client/registerCapability' }) + end) + + screen:expect({ grid = grid_with_dynamic_highlights }) + end) + it('does not clear document colors when one of several clients detaches', function() local client_id2 = exec_lua(function() _G.server2 = _G._create_server({