Merge #34797 refactor(lsp): enable()/is_enabled()

This commit is contained in:
Justin M. Keyes
2025-07-12 23:44:21 -04:00
committed by GitHub
9 changed files with 195 additions and 116 deletions

View File

@ -35,6 +35,8 @@ LSP
`vim.wo.conceallevel = 2`. `vim.wo.conceallevel = 2`.
• *vim.lsp.log.should_log()* Use |vim.lsp.log.set_format_func()| instead • *vim.lsp.log.should_log()* Use |vim.lsp.log.set_format_func()| instead
and return `nil` to omit entries from the logfile. and return `nil` to omit entries from the logfile.
• *vim.lsp.semantic_tokens.start()* Use `vim.lsp.semantic_tokens.enable(true)` instead
• *vim.lsp.semantic_tokens.stop()* Use `vim.lsp.semantic_tokens.enable(false)` instead
LUA LUA

View File

@ -2162,11 +2162,25 @@ is_enabled({filter}) *vim.lsp.inlay_hint.is_enabled()*
============================================================================== ==============================================================================
Lua module: vim.lsp.semantic_tokens *lsp-semantic_tokens* Lua module: vim.lsp.semantic_tokens *lsp-semantic_tokens*
enable({enable}, {filter}) *vim.lsp.semantic_tokens.enable()*
Enables or disables semantic tokens for the {filter}ed scope.
To "toggle", pass the inverse of `is_enabled()`: >lua
vim.lsp.semantic_tokens.enable(not vim.lsp.semantic_tokens.is_enabled())
<
Parameters: ~
• {enable} (`boolean?`) true/nil to enable, false to disable
• {filter} (`table?`) A table with the following fields:
• {bufnr}? (`integer`) Buffer number, or 0 for current
buffer, or nil for all.
• {client_id}? (`integer`) Client ID, or nil for all
force_refresh({bufnr}) *vim.lsp.semantic_tokens.force_refresh()* force_refresh({bufnr}) *vim.lsp.semantic_tokens.force_refresh()*
Force a refresh of all semantic tokens Force a refresh of all semantic tokens
Only has an effect if the buffer is currently active for semantic token Only has an effect if the buffer is currently active for semantic token
highlighting (|vim.lsp.semantic_tokens.start()| has been called for it) highlighting (|vim.lsp.semantic_tokens.enable()| has been called for it)
Parameters: ~ Parameters: ~
• {bufnr} (`integer?`) filter by buffer. All buffers if nil, current • {bufnr} (`integer?`) filter by buffer. All buffers if nil, current
@ -2215,38 +2229,14 @@ highlight_token({token}, {bufnr}, {client_id}, {hl_group}, {opts})
`vim.hl.priorities.semantic_tokens + 3`) Priority for `vim.hl.priorities.semantic_tokens + 3`) Priority for
the applied extmark. the applied extmark.
start({bufnr}, {client_id}, {opts}) *vim.lsp.semantic_tokens.start()* is_enabled({filter}) *vim.lsp.semantic_tokens.is_enabled()*
Start the semantic token highlighting engine for the given buffer with the Query whether semantic tokens is enabled in the {filter}ed scope
given client. The client must already be attached to the buffer.
NOTE: This is currently called automatically by
|vim.lsp.buf_attach_client()|. To opt-out of semantic highlighting with a
server that supports it, you can delete the semanticTokensProvider table
from the {server_capabilities} of your client in your |LspAttach| callback
or your configuration's `on_attach` callback: >lua
client.server_capabilities.semanticTokensProvider = nil
<
Parameters: ~ Parameters: ~
• {bufnr} (`integer`) Buffer number, or `0` for current buffer • {filter} (`table?`) A table with the following fields:
• {client_id} (`integer`) The ID of the |vim.lsp.Client| • {bufnr}? (`integer`) Buffer number, or 0 for current
• {opts} (`table?`) Optional keyword arguments buffer, or nil for all.
• debounce (integer, default: 200): Debounce token • {client_id}? (`integer`) Client ID, or nil for all
requests to the server by the given number in
milliseconds
stop({bufnr}, {client_id}) *vim.lsp.semantic_tokens.stop()*
Stop the semantic token highlighting engine for the given buffer with the
given client.
NOTE: This is automatically called by a |LspDetach| autocmd that is set up
as part of `start()`, so you should only need this function to manually
disengage the semantic token engine without fully detaching the LSP client
from the buffer.
Parameters: ~
• {bufnr} (`integer`) Buffer number, or `0` for current buffer
• {client_id} (`integer`) The ID of the |vim.lsp.Client|
============================================================================== ==============================================================================

View File

@ -84,6 +84,8 @@ LSP
• `root_markers` in |vim.lsp.Config| can now be ordered by priority. • `root_markers` in |vim.lsp.Config| can now be ordered by priority.
• The function set with |vim.lsp.log.set_format_func()| is now given all • The function set with |vim.lsp.log.set_format_func()| is now given all
arguments corresponding to a log entry instead of the individual arguments. arguments corresponding to a log entry instead of the individual arguments.
• `vim.lsp.semantic_tokens.start/stop` now renamed to
`vim.lsp.semantic_tokens.enable`
LUA LUA

View File

@ -87,7 +87,7 @@ end
--- Force `foldexpr()` to be re-evaluated, without opening folds. --- Force `foldexpr()` to be re-evaluated, without opening folds.
---@param bufnr integer ---@param bufnr integer
local function foldupdate(bufnr) local function foldupdate(bufnr)
if not api.nvim_buf_is_loaded(bufnr) or not vim.b[bufnr]._lsp_folding_range_enabled then if not api.nvim_buf_is_loaded(bufnr) or not vim.b[bufnr]._lsp_enable_folding_range then
return return
end end
for _, winid in ipairs(vim.fn.win_findbuf(bufnr)) do for _, winid in ipairs(vim.fn.win_findbuf(bufnr)) do
@ -159,7 +159,7 @@ end
--- `foldupdate()` is scheduled once after the request is completed. --- `foldupdate()` is scheduled once after the request is completed.
---@param client? vim.lsp.Client The client whose server supports `foldingRange`. ---@param client? vim.lsp.Client The client whose server supports `foldingRange`.
function State:refresh(client) function State:refresh(client)
if not vim.b._lsp_folding_range_enabled then if not vim.b._lsp_enable_folding_range then
return return
end end
@ -252,7 +252,7 @@ function State:new(bufnr)
pattern = 'foldexpr', pattern = 'foldexpr',
callback = function() callback = function()
if vim.v.option_type == 'global' or vim.api.nvim_get_current_buf() == bufnr then if vim.v.option_type == 'global' or vim.api.nvim_get_current_buf() == bufnr then
vim.b[bufnr]._lsp_folding_range_enabled = nil vim.b[bufnr]._lsp_enable_folding_range = nil
end end
end, end,
}) })
@ -349,8 +349,8 @@ end
function M.foldexpr(lnum) function M.foldexpr(lnum)
local bufnr = api.nvim_get_current_buf() local bufnr = api.nvim_get_current_buf()
local state = State.active[bufnr] local state = State.active[bufnr]
if not vim.b[bufnr]._lsp_folding_range_enabled then if not vim.b[bufnr]._lsp_enable_folding_range then
vim.b[bufnr]._lsp_folding_range_enabled = true vim.b[bufnr]._lsp_enable_folding_range = true
if state then if state then
state:refresh() state:refresh()
end end

View File

@ -1077,7 +1077,7 @@ function Client:on_attach(bufnr)
-- opt-out (deleting the semanticTokensProvider from capabilities) -- opt-out (deleting the semanticTokensProvider from capabilities)
vim.schedule(function() vim.schedule(function()
if vim.tbl_get(self.server_capabilities, 'semanticTokensProvider', 'full') then if vim.tbl_get(self.server_capabilities, 'semanticTokensProvider', 'full') then
lsp.semantic_tokens.start(bufnr, self.id) lsp.semantic_tokens._start(bufnr, self.id)
end end
if vim.tbl_get(self.server_capabilities, 'foldingRangeProvider') then if vim.tbl_get(self.server_capabilities, 'foldingRangeProvider') then
lsp._folding_range._setup(bufnr) lsp._folding_range._setup(bufnr)

View File

@ -7,6 +7,8 @@ local uv = vim.uv
local Capability = require('vim.lsp._capability') local Capability = require('vim.lsp._capability')
local M = {}
--- @class (private) STTokenRange --- @class (private) STTokenRange
--- @field line integer line number 0-based --- @field line integer line number 0-based
--- @field start_col integer start column 0-based --- @field start_col integer start column 0-based
@ -194,11 +196,13 @@ function STHighlighter:new(bufnr)
if not highlighter then if not highlighter then
return true return true
end end
highlighter:on_change() if M.is_enabled({ bufnr = buf }) then
highlighter:on_change()
end
end, end,
on_reload = function(_, buf) on_reload = function(_, buf)
local highlighter = STHighlighter.active[buf] local highlighter = STHighlighter.active[buf]
if highlighter then if highlighter and M.is_enabled({ bufnr = bufnr }) then
highlighter:reset() highlighter:reset()
highlighter:send_request() highlighter:send_request()
end end
@ -209,7 +213,9 @@ function STHighlighter:new(bufnr)
buffer = self.bufnr, buffer = self.bufnr,
group = self.augroup, group = self.augroup,
callback = function() callback = function()
self:send_request() if M.is_enabled({ bufnr = bufnr }) then
self:send_request()
end
end, end,
}) })
@ -582,7 +588,25 @@ function STHighlighter:reset_timer()
end end
end end
local M = {} ---@param bufnr (integer) Buffer number, or `0` for current buffer
---@param client_id (integer) The ID of the |vim.lsp.Client|
---@param debounce? (integer) (default: 200): Debounce token requests
--- to the server by the given number in milliseconds
function M._start(bufnr, client_id, debounce)
local highlighter = STHighlighter.active[bufnr]
if not highlighter then
highlighter = STHighlighter:new(bufnr)
highlighter.debounce = debounce or 200
else
highlighter.debounce = debounce or highlighter.debounce
end
highlighter:on_attach(client_id)
if M.is_enabled({ bufnr = bufnr }) then
highlighter:send_request()
end
end
--- Start the semantic token highlighting engine for the given buffer with the --- Start the semantic token highlighting engine for the given buffer with the
--- given client. The client must already be attached to the buffer. --- given client. The client must already be attached to the buffer.
@ -597,12 +621,14 @@ local M = {}
--- client.server_capabilities.semanticTokensProvider = nil --- client.server_capabilities.semanticTokensProvider = nil
--- ``` --- ```
--- ---
---@deprecated
---@param bufnr (integer) Buffer number, or `0` for current buffer ---@param bufnr (integer) Buffer number, or `0` for current buffer
---@param client_id (integer) The ID of the |vim.lsp.Client| ---@param client_id (integer) The ID of the |vim.lsp.Client|
---@param opts? (table) Optional keyword arguments ---@param opts? (table) Optional keyword arguments
--- - debounce (integer, default: 200): Debounce token requests --- - debounce (integer, default: 200): Debounce token requests
--- to the server by the given number in milliseconds --- to the server by the given number in milliseconds
function M.start(bufnr, client_id, opts) function M.start(bufnr, client_id, opts)
vim.deprecate('vim.lsp.semantic_tokens.start', 'vim.lsp.semantic_tokens.enable(true)', '0.13.0')
vim.validate('bufnr', bufnr, 'number') vim.validate('bufnr', bufnr, 'number')
vim.validate('client_id', client_id, 'number') vim.validate('client_id', client_id, 'number')
@ -633,17 +659,7 @@ function M.start(bufnr, client_id, opts)
return return
end end
local highlighter = STHighlighter.active[bufnr] M._start(bufnr, client_id, opts.debounce)
if not highlighter then
highlighter = STHighlighter:new(bufnr)
highlighter.debounce = opts.debounce or 200
else
highlighter.debounce = math.max(highlighter.debounce, opts.debounce or 200)
end
highlighter:on_attach(client_id)
highlighter:send_request()
end end
--- Stop the semantic token highlighting engine for the given buffer with the --- Stop the semantic token highlighting engine for the given buffer with the
@ -653,9 +669,11 @@ end
--- of `start()`, so you should only need this function to manually disengage the semantic --- of `start()`, so you should only need this function to manually disengage the semantic
--- token engine without fully detaching the LSP client from the buffer. --- token engine without fully detaching the LSP client from the buffer.
--- ---
---@deprecated
---@param bufnr (integer) Buffer number, or `0` for current buffer ---@param bufnr (integer) Buffer number, or `0` for current buffer
---@param client_id (integer) The ID of the |vim.lsp.Client| ---@param client_id (integer) The ID of the |vim.lsp.Client|
function M.stop(bufnr, client_id) function M.stop(bufnr, client_id)
vim.deprecate('vim.lsp.semantic_tokens.stop', 'vim.lsp.semantic_tokens.enable(false)', '0.13.0')
vim.validate('bufnr', bufnr, 'number') vim.validate('bufnr', bufnr, 'number')
vim.validate('client_id', client_id, 'number') vim.validate('client_id', client_id, 'number')
@ -673,6 +691,37 @@ function M.stop(bufnr, client_id)
end end
end end
--- Query whether semantic tokens is enabled in the {filter}ed scope
---@param filter? vim.lsp.enable.Filter
function M.is_enabled(filter)
return util._is_enabled('semantic_tokens', filter)
end
--- Enables or disables semantic tokens for the {filter}ed scope.
---
--- To "toggle", pass the inverse of `is_enabled()`:
---
--- ```lua
--- vim.lsp.semantic_tokens.enable(not vim.lsp.semantic_tokens.is_enabled())
--- ```
---
---@param enable? boolean true/nil to enable, false to disable
---@param filter? vim.lsp.enable.Filter
function M.enable(enable, filter)
util._enable('semantic_tokens', enable, filter)
for _, bufnr in ipairs(api.nvim_list_bufs()) do
local highlighter = STHighlighter.active[bufnr]
if highlighter then
if M.is_enabled({ bufnr = bufnr }) then
highlighter:send_request()
else
highlighter:reset()
end
end
end
end
--- @nodoc --- @nodoc
--- @class STTokenRangeInspect : STTokenRange --- @class STTokenRangeInspect : STTokenRange
--- @field client_id integer --- @field client_id integer
@ -736,7 +785,7 @@ end
--- Force a refresh of all semantic tokens --- Force a refresh of all semantic tokens
--- ---
--- Only has an effect if the buffer is currently active for semantic token --- Only has an effect if the buffer is currently active for semantic token
--- highlighting (|vim.lsp.semantic_tokens.start()| has been called for it) --- highlighting (|vim.lsp.semantic_tokens.enable()| has been called for it)
--- ---
---@param bufnr (integer|nil) filter by buffer. All buffers if nil, current ---@param bufnr (integer|nil) filter by buffer. All buffers if nil, current
--- buffer if 0 --- buffer if 0
@ -748,7 +797,7 @@ function M.force_refresh(bufnr)
for _, buffer in ipairs(buffers) do for _, buffer in ipairs(buffers) do
local highlighter = STHighlighter.active[buffer] local highlighter = STHighlighter.active[buffer]
if highlighter then if highlighter and M.is_enabled({ bufnr = bufnr }) then
highlighter:reset() highlighter:reset()
highlighter:send_request() highlighter:send_request()
end end
@ -831,4 +880,7 @@ api.nvim_set_decoration_provider(namespace, {
---@private ---@private
M.__STHighlighter = STHighlighter M.__STHighlighter = STHighlighter
-- Semantic tokens is enabled by default
util._enable('semantic_tokens', true)
return M return M

View File

@ -2340,6 +2340,85 @@ function M._refresh(method, opts)
end end
end end
---@param feature string
---@param client_id? integer
local function make_enable_var(feature, client_id)
return ('_lsp_enabled_%s%s'):format(feature, client_id and ('_client_%d'):format(client_id) or '')
end
---@class vim.lsp.enable.Filter
---@inlinedoc
---
--- Buffer number, or 0 for current buffer, or nil for all.
---@field bufnr? integer
---
--- Client ID, or nil for all
---@field client_id? integer
---@param feature string
---@param filter? vim.lsp.enable.Filter
function M._is_enabled(feature, filter)
vim.validate('feature', feature, 'string')
vim.validate('filter', filter, 'table', true)
filter = filter or {}
local bufnr = filter.bufnr
local client_id = filter.client_id
local var = make_enable_var(feature)
local client_var = make_enable_var(feature, client_id)
return vim.F.if_nil(client_id and vim.g[client_var], vim.g[var])
and vim.F.if_nil(bufnr and vim.b[bufnr][var], vim.g[var])
end
---@param feature 'semantic_tokens'
---@param enable? boolean
---@param filter? vim.lsp.enable.Filter
function M._enable(feature, enable, filter)
vim.validate('feature', feature, 'string')
vim.validate('enable', enable, 'boolean', true)
vim.validate('filter', filter, 'table', true)
enable = enable == nil or enable
filter = filter or {}
local bufnr = filter.bufnr
local client_id = filter.client_id
assert(
not (bufnr and client_id),
'Only one of `bufnr` or `client_id` filters can be specified at a time.'
)
local var = make_enable_var(feature)
local client_var = make_enable_var(feature, client_id)
if client_id then
if enable == vim.g[var] then
vim.g[client_var] = nil
else
vim.g[client_var] = enable
end
elseif bufnr then
if enable == vim.g[var] then
vim.b[bufnr][var] = nil
else
vim.b[bufnr][var] = enable
end
else
vim.g[var] = enable
for _, it_bufnr in ipairs(api.nvim_list_bufs()) do
if api.nvim_buf_is_loaded(it_bufnr) and vim.b[it_bufnr][var] == enable then
vim.b[it_bufnr][var] = nil
end
end
for _, it_client in ipairs(vim.lsp.get_clients()) do
local it_client_var = make_enable_var(feature, it_client.id)
if vim.g[it_client_var] and vim.g[it_client_var] == enable then
vim.g[it_client_var] = nil
end
end
end
end
M._get_line_byte_from_position = get_line_byte_from_position M._get_line_byte_from_position = get_line_byte_from_position
---@nodoc ---@nodoc

View File

@ -135,25 +135,25 @@ static int foldLevel(linenr_T lnum)
command([[split]]) command([[split]])
end) end)
it('controls the value of `b:_lsp_folding_range_enabled`', function() it('controls the value of `b:_lsp_enable_folding_range`', function()
eq( eq(
true, true,
exec_lua(function() exec_lua(function()
return vim.b._lsp_folding_range_enabled return vim.b._lsp_enable_folding_range
end) end)
) )
command [[setlocal foldexpr=]] command [[setlocal foldexpr=]]
eq( eq(
nil, nil,
exec_lua(function() exec_lua(function()
return vim.b._lsp_folding_range_enabled return vim.b._lsp_enable_folding_range
end) end)
) )
command([[set foldexpr=v:lua.vim.lsp.foldexpr()]]) command([[set foldexpr=v:lua.vim.lsp.foldexpr()]])
eq( eq(
true, true,
exec_lua(function() exec_lua(function()
return vim.b._lsp_folding_range_enabled return vim.b._lsp_enable_folding_range
end) end)
) )
end) end)

View File

@ -8,9 +8,7 @@ local dedent = t.dedent
local eq = t.eq local eq = t.eq
local exec_lua = n.exec_lua local exec_lua = n.exec_lua
local feed = n.feed local feed = n.feed
local feed_command = n.feed_command
local insert = n.insert local insert = n.insert
local matches = t.matches
local api = n.api local api = n.api
local clear_notrace = t_lsp.clear_notrace local clear_notrace = t_lsp.clear_notrace
@ -255,10 +253,10 @@ describe('semantic token highlighting', function()
end) end)
it( it(
'buffer is highlighted and unhighlighted when semantic token highlighting is started and stopped', 'buffer is highlighted and unhighlighted when semantic token highlighting is enabled and disabled',
function() function()
local bufnr = n.api.nvim_get_current_buf() local bufnr = n.api.nvim_get_current_buf()
local client_id = exec_lua(function() exec_lua(function()
vim.api.nvim_win_set_buf(0, bufnr) vim.api.nvim_win_set_buf(0, bufnr)
return vim.lsp.start({ name = 'dummy', cmd = _G.server.cmd }) return vim.lsp.start({ name = 'dummy', cmd = _G.server.cmd })
end) end)
@ -268,7 +266,7 @@ describe('semantic token highlighting', function()
exec_lua(function() exec_lua(function()
--- @diagnostic disable-next-line:duplicate-set-field --- @diagnostic disable-next-line:duplicate-set-field
vim.notify = function() end vim.notify = function() end
vim.lsp.semantic_tokens.stop(bufnr, client_id) vim.lsp.semantic_tokens.enable(false)
end) end)
screen:expect { screen:expect {
@ -291,7 +289,7 @@ describe('semantic token highlighting', function()
} }
exec_lua(function() exec_lua(function()
vim.lsp.semantic_tokens.start(bufnr, client_id) vim.lsp.semantic_tokens.enable(true)
end) end)
screen:expect { screen:expect {
@ -316,7 +314,7 @@ describe('semantic token highlighting', function()
) )
it('highlights start and stop when using "0" for current buffer', function() it('highlights start and stop when using "0" for current buffer', function()
local client_id = exec_lua(function() exec_lua(function()
return vim.lsp.start({ name = 'dummy', cmd = _G.server.cmd }) return vim.lsp.start({ name = 'dummy', cmd = _G.server.cmd })
end) end)
@ -325,7 +323,7 @@ describe('semantic token highlighting', function()
exec_lua(function() exec_lua(function()
--- @diagnostic disable-next-line:duplicate-set-field --- @diagnostic disable-next-line:duplicate-set-field
vim.notify = function() end vim.notify = function() end
vim.lsp.semantic_tokens.stop(0, client_id) vim.lsp.semantic_tokens.enable(false, { bufnr = 0 })
end) end)
screen:expect { screen:expect {
@ -348,7 +346,7 @@ describe('semantic token highlighting', function()
} }
exec_lua(function() exec_lua(function()
vim.lsp.semantic_tokens.start(0, client_id) vim.lsp.semantic_tokens.enable(true, { bufnr = 0 })
end) end)
screen:expect { screen:expect {
@ -475,8 +473,8 @@ describe('semantic token highlighting', function()
| |
]], ]],
} }
feed_command('%s/int x/int x()/') feed(':%s/int x/int x()/<CR>')
feed_command('noh') feed(':noh<CR>')
screen:expect { screen:expect {
grid = [[ grid = [[
#include <iostream> | #include <iostream> |
@ -496,36 +494,6 @@ describe('semantic token highlighting', function()
} }
end) end)
it('prevents starting semantic token highlighting with invalid conditions', function()
local client_id = exec_lua(function()
_G.notifications = {}
--- @diagnostic disable-next-line:duplicate-set-field
vim.notify = function(...)
table.insert(_G.notifications, 1, { ... })
end
return vim.lsp.start({ name = 'dummy', cmd = _G.server.cmd }, { attach = false })
end)
eq(false, exec_lua('return vim.lsp.buf_is_attached(0, ...)', client_id))
insert(text)
matches(
'%[LSP%] Client with id %d not attached to buffer %d',
exec_lua(function()
vim.lsp.semantic_tokens.start(0, client_id)
return _G.notifications[1][1]
end)
)
matches(
'%[LSP%] No client with id %d',
exec_lua(function()
vim.lsp.semantic_tokens.start(0, client_id + 1)
return _G.notifications[1][1]
end)
)
end)
it( it(
'opt-out: does not activate semantic token highlighting if disabled in client attach', 'opt-out: does not activate semantic token highlighting if disabled in client attach',
function() function()
@ -562,19 +530,6 @@ describe('semantic token highlighting', function()
]], ]],
} }
eq(
'[LSP] Server does not support semantic tokens',
exec_lua(function()
local notifications = {}
--- @diagnostic disable-next-line:duplicate-set-field
vim.notify = function(...)
table.insert(notifications, 1, { ... })
end
vim.lsp.semantic_tokens.start(0, client_id)
return notifications[1][1]
end)
)
screen:expect { screen:expect {
grid = [[ grid = [[
#include <iostream> | #include <iostream> |
@ -720,8 +675,8 @@ describe('semantic token highlighting', function()
| |
]], ]],
} }
feed_command('%s/int x/int x()/') feed(':%s/int x/int x()/<CR>')
feed_command('noh') feed(':noh<CR>')
-- the highlights don't change because our fake server sent the exact -- the highlights don't change because our fake server sent the exact
-- same result for the same method (the full request). "x" would have -- same result for the same method (the full request). "x" would have
@ -1599,8 +1554,7 @@ int main()
-- speed up vim.api.nvim_buf_set_lines calls by changing debounce to 10 for these tests -- speed up vim.api.nvim_buf_set_lines calls by changing debounce to 10 for these tests
vim.schedule(function() vim.schedule(function()
vim.lsp.semantic_tokens.stop(bufnr, client_id) vim.lsp.semantic_tokens._start(bufnr, client_id, 10)
vim.lsp.semantic_tokens.start(bufnr, client_id, { debounce = 10 })
end) end)
return client_id return client_id
end, test.legend, test.response1, test.response2) end, test.legend, test.response1, test.response2)