mirror of
https://github.com/LazyVim/LazyVim.git
synced 2025-06-24 17:58:51 +02:00
feat(lsp): properly update certain Neovim functionlity based on dynamic capabilities. See #3244. Fixes #3246
This commit is contained in:
parent
97862f4259
commit
20e002f9f0
2 changed files with 85 additions and 45 deletions
|
@ -121,16 +121,8 @@ return {
|
||||||
require("lazyvim.plugins.lsp.keymaps").on_attach(client, buffer)
|
require("lazyvim.plugins.lsp.keymaps").on_attach(client, buffer)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local register_capability = vim.lsp.handlers["client/registerCapability"]
|
LazyVim.lsp.setup_dynamic_capability()
|
||||||
|
LazyVim.lsp.on_dynamic_capability(require("lazyvim.plugins.lsp.keymaps").on_attach)
|
||||||
vim.lsp.handlers["client/registerCapability"] = function(err, res, ctx)
|
|
||||||
---@diagnostic disable-next-line: no-unknown
|
|
||||||
local ret = register_capability(err, res, ctx)
|
|
||||||
local client = vim.lsp.get_client_by_id(ctx.client_id)
|
|
||||||
local buffer = vim.api.nvim_get_current_buf()
|
|
||||||
require("lazyvim.plugins.lsp.keymaps").on_attach(client, buffer)
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
LazyVim.lsp.words.setup(opts.document_highlight)
|
LazyVim.lsp.words.setup(opts.document_highlight)
|
||||||
|
|
||||||
|
@ -148,24 +140,19 @@ return {
|
||||||
if vim.fn.has("nvim-0.10") == 1 then
|
if vim.fn.has("nvim-0.10") == 1 then
|
||||||
-- inlay hints
|
-- inlay hints
|
||||||
if opts.inlay_hints.enabled then
|
if opts.inlay_hints.enabled then
|
||||||
LazyVim.lsp.on_attach(function(client, buffer)
|
LazyVim.lsp.on_supports_method("textDocument/inlayHint", function(client, buffer)
|
||||||
if client.supports_method("textDocument/inlayHint") then
|
LazyVim.toggle.inlay_hints(buffer, true)
|
||||||
LazyVim.toggle.inlay_hints(buffer, true)
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- code lens
|
-- code lens
|
||||||
if opts.codelens.enabled and vim.lsp.codelens then
|
if opts.codelens.enabled and vim.lsp.codelens then
|
||||||
LazyVim.lsp.on_attach(function(client, buffer)
|
LazyVim.lsp.on_supports_method("textDocument/codeLens", function(client, buffer)
|
||||||
if client.supports_method("textDocument/codeLens") then
|
vim.lsp.codelens.refresh()
|
||||||
vim.lsp.codelens.refresh()
|
vim.api.nvim_create_autocmd({ "BufEnter", "CursorHold", "InsertLeave" }, {
|
||||||
--- autocmd BufEnter,CursorHold,InsertLeave <buffer> lua vim.lsp.codelens.refresh()
|
buffer = buffer,
|
||||||
vim.api.nvim_create_autocmd({ "BufEnter", "CursorHold", "InsertLeave" }, {
|
callback = vim.lsp.codelens.refresh,
|
||||||
buffer = buffer,
|
})
|
||||||
callback = vim.lsp.codelens.refresh,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,14 +5,14 @@ local M = {}
|
||||||
|
|
||||||
---@param opts? lsp.Client.filter
|
---@param opts? lsp.Client.filter
|
||||||
function M.get_clients(opts)
|
function M.get_clients(opts)
|
||||||
local ret = {} ---@type lsp.Client[]
|
local ret = {} ---@type vim.lsp.Client[]
|
||||||
if vim.lsp.get_clients then
|
if vim.lsp.get_clients then
|
||||||
ret = vim.lsp.get_clients(opts)
|
ret = vim.lsp.get_clients(opts)
|
||||||
else
|
else
|
||||||
---@diagnostic disable-next-line: deprecated
|
---@diagnostic disable-next-line: deprecated
|
||||||
ret = vim.lsp.get_active_clients(opts)
|
ret = vim.lsp.get_active_clients(opts)
|
||||||
if opts and opts.method then
|
if opts and opts.method then
|
||||||
---@param client lsp.Client
|
---@param client vim.lsp.Client
|
||||||
ret = vim.tbl_filter(function(client)
|
ret = vim.tbl_filter(function(client)
|
||||||
return client.supports_method(opts.method, { bufnr = opts.bufnr })
|
return client.supports_method(opts.method, { bufnr = opts.bufnr })
|
||||||
end, ret)
|
end, ret)
|
||||||
|
@ -21,17 +21,66 @@ function M.get_clients(opts)
|
||||||
return opts and opts.filter and vim.tbl_filter(opts.filter, ret) or ret
|
return opts and opts.filter and vim.tbl_filter(opts.filter, ret) or ret
|
||||||
end
|
end
|
||||||
|
|
||||||
---@param on_attach fun(client:lsp.Client, buffer)
|
---@param on_attach fun(client:vim.lsp.Client, buffer)
|
||||||
function M.on_attach(on_attach)
|
function M.on_attach(on_attach)
|
||||||
vim.api.nvim_create_autocmd("LspAttach", {
|
return vim.api.nvim_create_autocmd("LspAttach", {
|
||||||
callback = function(args)
|
callback = function(args)
|
||||||
local buffer = args.buf ---@type number
|
local buffer = args.buf ---@type number
|
||||||
local client = vim.lsp.get_client_by_id(args.data.client_id)
|
local client = vim.lsp.get_client_by_id(args.data.client_id)
|
||||||
on_attach(client, buffer)
|
if client then
|
||||||
|
return on_attach(client, buffer)
|
||||||
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
M._dynamic_handlers = {} ---@type fun(client:vim.lsp.Client, buffer)[]
|
||||||
|
|
||||||
|
function M.setup_dynamic_capability()
|
||||||
|
local register_capability = vim.lsp.handlers["client/registerCapability"]
|
||||||
|
|
||||||
|
vim.lsp.handlers["client/registerCapability"] = function(err, res, ctx)
|
||||||
|
---@diagnostic disable-next-line: no-unknown
|
||||||
|
local ret = register_capability(err, res, ctx)
|
||||||
|
local client = vim.lsp.get_client_by_id(ctx.client_id)
|
||||||
|
local buffer = vim.api.nvim_get_current_buf()
|
||||||
|
if client then
|
||||||
|
M._dynamic_handlers = vim.tbl_filter(function(handler)
|
||||||
|
return handler(client, buffer) ~= false
|
||||||
|
end, M._dynamic_handlers)
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param fn fun(client:vim.lsp.Client, buffer)
|
||||||
|
function M.on_dynamic_capability(fn)
|
||||||
|
table.insert(M._dynamic_handlers, fn)
|
||||||
|
end
|
||||||
|
|
||||||
|
---@type table<string,table<vim.lsp.Client, table<number,boolean>>>
|
||||||
|
M._on_supports_method = {}
|
||||||
|
|
||||||
|
---@param method string
|
||||||
|
---@param fn fun(client:vim.lsp.Client, buffer)
|
||||||
|
function M.on_supports_method(method, fn)
|
||||||
|
M._on_supports_method[method] = M._on_supports_method[method] or setmetatable({}, { __mode = "k" })
|
||||||
|
|
||||||
|
---@param client vim.lsp.Client
|
||||||
|
local function check(client, buffer)
|
||||||
|
M._on_supports_method[method][client] = M._on_supports_method[method][client] or {}
|
||||||
|
if M._on_supports_method[method][client][buffer] then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if client.supports_method(method, { bufnr = buffer }) then
|
||||||
|
M._on_supports_method[method][client][buffer] = true
|
||||||
|
fn(client, buffer)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
M.on_attach(check)
|
||||||
|
M.on_dynamic_capability(check)
|
||||||
|
end
|
||||||
|
|
||||||
---@param from string
|
---@param from string
|
||||||
---@param to string
|
---@param to string
|
||||||
function M.on_rename(from, to)
|
function M.on_rename(from, to)
|
||||||
|
@ -89,12 +138,12 @@ function M.formatter(opts)
|
||||||
end,
|
end,
|
||||||
sources = function(buf)
|
sources = function(buf)
|
||||||
local clients = M.get_clients(LazyVim.merge({}, filter, { bufnr = buf }))
|
local clients = M.get_clients(LazyVim.merge({}, filter, { bufnr = buf }))
|
||||||
---@param client lsp.Client
|
---@param client vim.lsp.Client
|
||||||
local ret = vim.tbl_filter(function(client)
|
local ret = vim.tbl_filter(function(client)
|
||||||
return client.supports_method("textDocument/formatting")
|
return client.supports_method("textDocument/formatting")
|
||||||
or client.supports_method("textDocument/rangeFormatting")
|
or client.supports_method("textDocument/rangeFormatting")
|
||||||
end, clients)
|
end, clients)
|
||||||
---@param client lsp.Client
|
---@param client vim.lsp.Client
|
||||||
return vim.tbl_map(function(client)
|
return vim.tbl_map(function(client)
|
||||||
return client.name
|
return client.name
|
||||||
end, ret)
|
end, ret)
|
||||||
|
@ -143,22 +192,26 @@ function M.words.setup(opts)
|
||||||
return handler(err, result, ctx, config)
|
return handler(err, result, ctx, config)
|
||||||
end
|
end
|
||||||
|
|
||||||
M.on_attach(function(client, buf)
|
M.on_supports_method("textDocument/documentHighlight", function(client, buf)
|
||||||
if client.supports_method("textDocument/documentHighlight") then
|
local group = vim.api.nvim_create_augroup("lsp_word_" .. buf, { clear = true })
|
||||||
vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI", "CursorMoved", "CursorMovedI" }, {
|
vim.api.nvim_create_autocmd({ "CursorHold", "CursorHoldI", "CursorMoved", "CursorMovedI" }, {
|
||||||
group = vim.api.nvim_create_augroup("lsp_word_" .. buf, { clear = true }),
|
group = group,
|
||||||
buffer = buf,
|
buffer = buf,
|
||||||
callback = function(ev)
|
callback = function(ev)
|
||||||
if not M.words.at() then
|
if not M.words.at() then
|
||||||
if ev.event:find("CursorMoved") then
|
if ev.event:find("CursorMoved") then
|
||||||
vim.lsp.buf.clear_references()
|
vim.lsp.buf.clear_references()
|
||||||
else
|
else
|
||||||
vim.lsp.buf.document_highlight()
|
vim.lsp.buf.document_highlight()
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end,
|
end
|
||||||
})
|
end,
|
||||||
end
|
})
|
||||||
|
vim.api.nvim_create_autocmd("LspDetach", {
|
||||||
|
callback = function()
|
||||||
|
vim.api.nvim_create_augroup("lsp_word_" .. buf, { clear = true })
|
||||||
|
end,
|
||||||
|
})
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue