neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit 7c3e579a907e3d27caa6dfe67f0f4a6009f94609
parent 81d8198bda0f5651de36f7587589ec1165c48843
Author: Yi Ming <ofseed@foxmail.com>
Date:   Mon, 21 Jul 2025 12:56:01 +0800

refactor(lsp): register all derived `Capability` prototypes

Diffstat:
Mruntime/lua/vim/lsp/_capability.lua | 34++++++++++++++++++++++++++--------
Mruntime/lua/vim/lsp/_folding_range.lua | 2--
Mruntime/lua/vim/lsp/health.lua | 11+++--------
3 files changed, 29 insertions(+), 18 deletions(-)

diff --git a/runtime/lua/vim/lsp/_capability.lua b/runtime/lua/vim/lsp/_capability.lua @@ -1,18 +1,28 @@ local api = vim.api ---- `vim.lsp.Capability` is expected to be created one-to-one with a buffer ---- when there is at least one supported client attached to that buffer, ---- and will be destroyed when all supporting clients are detached. +---@alias vim.lsp.capability.Name +---| 'semantic_tokens' +---| 'folding_range' + +--- Tracks all supported capabilities, all of which derive from `vim.lsp.Capability`. +--- Returns capability *prototypes*, not their instances. +---@type table<vim.lsp.capability.Name, vim.lsp.Capability> +local all_capabilities = {} + +-- Abstract base class (not instantiable directly). +-- For each buffer that has at least one supported client attached, +-- exactly one instance of each concrete subclass is created. +-- That instance is destroyed once all supporting clients detach from the buffer. ---@class vim.lsp.Capability --- +--- Static field as the identifier of the LSP capability it supports. +---@field name vim.lsp.capability.Name +--- --- Static field for retrieving the instance associated with a specific `bufnr`. --- ---- Index inthe form of `bufnr` -> `capability` +--- Index in the form of `bufnr` -> `capability` ---@field active table<integer, vim.lsp.Capability?> --- ---- The LSP feature it supports. ----@field name string ---- --- Buffer number it associated with. ---@field bufnr integer --- @@ -33,7 +43,13 @@ function M:new(bufnr) -- `Class` may be a subtype of `Capability`, as it supports inheritance. ---@type vim.lsp.Capability local Class = self - assert(Class.name and Class.active, 'Do not instantiate the abstract class') + if M == Class then + error('Do not instantiate the abstract class') + elseif all_capabilities[Class.name] and all_capabilities[Class.name] ~= Class then + error('Duplicated capability name') + else + all_capabilities[Class.name] = Class + end ---@type vim.lsp.Capability self = setmetatable({}, Class) @@ -84,4 +100,6 @@ function M:on_detach(client_id) self.client_state[client_id] = nil end +M.all = all_capabilities + return M diff --git a/runtime/lua/vim/lsp/_folding_range.lua b/runtime/lua/vim/lsp/_folding_range.lua @@ -368,6 +368,4 @@ function M.foldexpr(lnum) return level and (level[2] or '') .. (level[1] or '0') or '0' end -M.__FoldEvaluator = State - return M diff --git a/runtime/lua/vim/lsp/health.lua b/runtime/lua/vim/lsp/health.lua @@ -30,15 +30,10 @@ end local function check_active_features() vim.health.start('vim.lsp: Active Features') - ---@type vim.lsp.Capability[] - local features = { - require('vim.lsp.semantic_tokens').__STHighlighter, - require('vim.lsp._folding_range').__FoldEvaluator, - } - for _, feature in ipairs(features) do + for _, Capability in pairs(vim.lsp._capability.all) do ---@type string[] local buf_infos = {} - for bufnr, instance in pairs(feature.active) do + for bufnr, instance in pairs(Capability.active) do local client_info = vim .iter(pairs(instance.client_state)) :map(function(client_id) @@ -58,7 +53,7 @@ local function check_active_features() end report_info(table.concat({ - feature.name, + Capability.name, '- Active buffers:', string.format(table.concat(buf_infos, '\n')), }, '\n'))