commit 8f5bd569c5414de8c38918f42f866dfb815a7264
parent 5c15df449a8772a0ddde3aa42ab67a0bde836939
Author: Maria José Solano <majosolano99@gmail.com>
Date: Sun, 4 May 2025 09:00:21 -0500
feat(lsp): support `documentColor` dynamic registration #33800
Diffstat:
5 files changed, 73 insertions(+), 27 deletions(-)
diff --git 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
@@ -173,16 +173,6 @@ local function buf_clear(bufnr)
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)
reset_bufstate(bufnr, false)
@@ -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
@@ -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
@@ -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
@@ -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({