diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 7d362da576..de279f6604 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -300,6 +300,8 @@ LSP |hl-LspReferenceTarget| highlight group. • Support for `textDocument/codeLens` |lsp-codelens| has been reimplemented: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#textDocument_codeLens +• Support for `workspace/codeLens/refresh`: + https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#codeLens_refresh LUA diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua index 1baba2a06a..3b72b1990b 100644 --- a/runtime/lua/vim/lsp/codelens.lua +++ b/runtime/lua/vim/lsp/codelens.lua @@ -123,9 +123,10 @@ function Provider:handler(err, result, ctx) self.version = ctx.version end ----@private +---@package ---@param client_id? integer -function Provider:request(client_id) +---@param on_response? function +function Provider:request(client_id, on_response) ---@type lsp.CodeLensParams local params = { textDocument = util.make_text_document_params(self.bufnr) } for id in pairs(self.client_state) do @@ -133,6 +134,10 @@ function Provider:request(client_id) local client = assert(vim.lsp.get_client_by_id(id)) client:request('textDocument/codeLens', params, function(...) self:handler(...) + + if on_response then + on_response() + end end, self.bufnr) end end @@ -404,6 +409,28 @@ function M.run(opts) end end +--- |lsp-handler| for the method `workspace/codeLens/refresh` +--- +---@private +---@type lsp.Handler +function M.on_refresh(err, _, ctx) + if err then + return vim.NIL + end + + for bufnr, provider in pairs(Provider.active) do + for client_id in pairs(provider.client_state) do + if client_id == ctx.client_id then + provider:request(client_id, function() + provider.row_version = {} + vim.api.nvim__redraw({ buf = bufnr, valid = true, flush = false }) + end) + end + end + end + return vim.NIL +end + ---@deprecated ---@param client_id? integer ---@param bufnr? integer diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index 722e3a17c3..1f6f22cfc8 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -649,6 +649,11 @@ RSC['window/showDocument'] = function(_, params, ctx) return { success = success or false } end +---@see https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#codeLens_refresh +RSC['workspace/codeLens/refresh'] = function(err, result, ctx) + return vim.lsp.codelens.on_refresh(err, result, ctx) +end + ---@see https://microsoft.github.io/language-server-protocol/specification/#diagnostic_refresh RSC['workspace/diagnostic/refresh'] = function(err, result, ctx) return vim.lsp.diagnostic.on_refresh(err, result, ctx) diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua index 6e4b1f713b..95550a8534 100644 --- a/runtime/lua/vim/lsp/protocol.lua +++ b/runtime/lua/vim/lsp/protocol.lua @@ -604,6 +604,9 @@ function protocol.make_client_capabilities() dynamicRegistration = sysname == 'Darwin' or sysname == 'Windows_NT', relativePatternSupport = true, }, + codeLens = { + refreshSupport = true, + }, inlayHint = { refreshSupport = true, }, diff --git a/test/functional/plugin/lsp/codelens_spec.lua b/test/functional/plugin/lsp/codelens_spec.lua index ee9b81fb53..f9856ed90f 100644 --- a/test/functional/plugin/lsp/codelens_spec.lua +++ b/test/functional/plugin/lsp/codelens_spec.lua @@ -9,6 +9,7 @@ local eq = t.eq local api = n.api local exec_lua = n.exec_lua local insert = n.insert +local feed = n.feed local clear_notrace = t_lsp.clear_notrace local create_server_definition = t_lsp.create_server_definition @@ -242,6 +243,58 @@ describe('vim.lsp.codelens', function() }, result) end) + it('refreshes code lenses on request', function() + feed('ggdd') + + screen:expect([[ + ^a: i32, {1:1 implementation} | + b: String, | + } | + | + impl S { | + fn new(a: i32, b: String) -> Self { | + S { a, b } | + } | + } | + | + fn main() { {1:▶︎ Run } | + let s = S::new(42, String::from("Hello, world!"))| + ; | + println!("S.a: {}, S.b: {}", s.a, s.b); | + } | + | + {1:~ }|*3 + | + ]]) + exec_lua(function() + vim.lsp.codelens.on_refresh( + nil, + nil, + { method = 'workspace/codeLens/refresh', client_id = client_id } + ) + end) + screen:expect([[ + ^a: i32, {1:1 implementation} | + b: String, | + } | + | + impl S { | + fn new(a: i32, b: String) -> Self { | + S { a, b } | + } | + } | + | + fn main() { | + let s = S::new(42, String::from("Hello, world!"))| + ; {1:▶︎ Run } | + println!("S.a: {}, S.b: {}", s.a, s.b); | + } | + | + {1:~ }|*3 + | + ]]) + end) + after_each(function() api.nvim_exec_autocmds('VimLeavePre', { modeline = false }) end)