refactor(lsp): rename vim.lsp.semantic_tokens start/stop to enable()

This commit is contained in:
Yi Ming
2025-07-07 11:58:44 +08:00
parent a8d9f3331e
commit 7e8aa0585e
6 changed files with 103 additions and 102 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

@ -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

@ -9,7 +9,6 @@ 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 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
@ -254,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)
@ -267,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 {
@ -290,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 {
@ -315,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)
@ -324,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 {
@ -347,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 {
@ -495,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()
@ -561,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> |
@ -1598,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)