aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp/semantic_tokens.lua
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/lua/vim/lsp/semantic_tokens.lua')
-rw-r--r--runtime/lua/vim/lsp/semantic_tokens.lua110
1 files changed, 65 insertions, 45 deletions
diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua
index 8182457dd0..215e5f41aa 100644
--- a/runtime/lua/vim/lsp/semantic_tokens.lua
+++ b/runtime/lua/vim/lsp/semantic_tokens.lua
@@ -99,11 +99,12 @@ local function tokens_to_ranges(data, bufnr, client, request)
local legend = client.server_capabilities.semanticTokensProvider.legend
local token_types = legend.tokenTypes
local token_modifiers = legend.tokenModifiers
+ local encoding = client.offset_encoding
local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false)
local ranges = {} ---@type STTokenRange[]
local start = uv.hrtime()
- local ms_to_ns = 1000 * 1000
+ local ms_to_ns = 1e6
local yield_interval_ns = 5 * ms_to_ns
local co, is_main = coroutine.running()
@@ -135,20 +136,13 @@ local function tokens_to_ranges(data, bufnr, client, request)
-- data[i+3] +1 because Lua tables are 1-indexed
local token_type = token_types[data[i + 3] + 1]
- local modifiers = modifiers_from_number(data[i + 4], token_modifiers)
-
- local function _get_byte_pos(col)
- if col > 0 then
- local buf_line = lines[line + 1] or ''
- return util._str_byteindex_enc(buf_line, col, client.offset_encoding)
- end
- return col
- end
-
- local start_col = _get_byte_pos(start_char)
- local end_col = _get_byte_pos(start_char + data[i + 2])
if token_type then
+ local modifiers = modifiers_from_number(data[i + 4], token_modifiers)
+ local end_char = start_char + data[i + 2]
+ local buf_line = lines and lines[line + 1] or ''
+ local start_col = vim.str_byteindex(buf_line, encoding, start_char, false)
+ local end_col = vim.str_byteindex(buf_line, encoding, end_char, false)
ranges[#ranges + 1] = {
line = line,
start_col = start_col,
@@ -386,6 +380,37 @@ function STHighlighter:process_response(response, client, version)
api.nvim__redraw({ buf = self.bufnr, valid = true })
end
+--- @param bufnr integer
+--- @param ns integer
+--- @param token STTokenRange
+--- @param hl_group string
+--- @param priority integer
+local function set_mark(bufnr, ns, token, hl_group, priority)
+ vim.api.nvim_buf_set_extmark(bufnr, ns, token.line, token.start_col, {
+ hl_group = hl_group,
+ end_col = token.end_col,
+ priority = priority,
+ strict = false,
+ })
+end
+
+--- @param lnum integer
+--- @param foldend integer?
+--- @return boolean, integer?
+local function check_fold(lnum, foldend)
+ if foldend and lnum <= foldend then
+ return true, foldend
+ end
+
+ local folded = vim.fn.foldclosed(lnum)
+
+ if folded == -1 then
+ return false, nil
+ end
+
+ return folded ~= lnum, vim.fn.foldclosedend(lnum)
+end
+
--- on_win handler for the decoration provider (see |nvim_set_decoration_provider|)
---
--- If there is a current result for the buffer and the version matches the
@@ -439,13 +464,14 @@ function STHighlighter:on_win(topline, botline)
-- finishes, clangd sends a refresh request which lets the client
-- re-synchronize the tokens.
- local set_mark = function(token, hl_group, delta)
- vim.api.nvim_buf_set_extmark(self.bufnr, state.namespace, token.line, token.start_col, {
- hl_group = hl_group,
- end_col = token.end_col,
- priority = vim.highlight.priorities.semantic_tokens + delta,
- strict = false,
- })
+ local function set_mark0(token, hl_group, delta)
+ set_mark(
+ self.bufnr,
+ state.namespace,
+ token,
+ hl_group,
+ vim.hl.priorities.semantic_tokens + delta
+ )
end
local ft = vim.bo[self.bufnr].filetype
@@ -453,13 +479,19 @@ function STHighlighter:on_win(topline, botline)
local first = lower_bound(highlights, topline, 1, #highlights + 1)
local last = upper_bound(highlights, botline, first, #highlights + 1) - 1
+ --- @type boolean?, integer?
+ local is_folded, foldend
+
for i = first, last do
local token = highlights[i]
- if not token.marked then
- set_mark(token, string.format('@lsp.type.%s.%s', token.type, ft), 0)
- for modifier, _ in pairs(token.modifiers) do
- set_mark(token, string.format('@lsp.mod.%s.%s', modifier, ft), 1)
- set_mark(token, string.format('@lsp.typemod.%s.%s.%s', token.type, modifier, ft), 2)
+
+ is_folded, foldend = check_fold(token.line + 1, foldend)
+
+ if not is_folded and not token.marked then
+ set_mark0(token, string.format('@lsp.type.%s.%s', token.type, ft), 0)
+ for modifier in pairs(token.modifiers) do
+ set_mark0(token, string.format('@lsp.mod.%s.%s', modifier, ft), 1)
+ set_mark0(token, string.format('@lsp.typemod.%s.%s.%s', token.type, modifier, ft), 2)
end
token.marked = true
@@ -565,10 +597,8 @@ local M = {}
--- - debounce (integer, default: 200): Debounce token requests
--- to the server by the given number in milliseconds
function M.start(bufnr, client_id, opts)
- vim.validate({
- bufnr = { bufnr, 'n', false },
- client_id = { client_id, 'n', false },
- })
+ vim.validate('bufnr', bufnr, 'number')
+ vim.validate('client_id', client_id, 'number')
if bufnr == 0 then
bufnr = api.nvim_get_current_buf()
@@ -622,10 +652,8 @@ end
---@param bufnr (integer) Buffer number, or `0` for current buffer
---@param client_id (integer) The ID of the |vim.lsp.Client|
function M.stop(bufnr, client_id)
- vim.validate({
- bufnr = { bufnr, 'n', false },
- client_id = { client_id, 'n', false },
- })
+ vim.validate('bufnr', bufnr, 'number')
+ vim.validate('client_id', client_id, 'number')
if bufnr == 0 then
bufnr = api.nvim_get_current_buf()
@@ -708,9 +736,7 @@ end
---@param bufnr (integer|nil) filter by buffer. All buffers if nil, current
--- buffer if 0
function M.force_refresh(bufnr)
- vim.validate({
- bufnr = { bufnr, 'n', true },
- })
+ vim.validate('bufnr', bufnr, 'number', true)
local buffers = bufnr == nil and vim.tbl_keys(STHighlighter.active)
or bufnr == 0 and { api.nvim_get_current_buf() }
@@ -729,7 +755,7 @@ end
--- @inlinedoc
---
--- Priority for the applied extmark.
---- (Default: `vim.highlight.priorities.semantic_tokens + 3`)
+--- (Default: `vim.hl.priorities.semantic_tokens + 3`)
--- @field priority? integer
--- Highlight a semantic token.
@@ -757,15 +783,9 @@ function M.highlight_token(token, bufnr, client_id, hl_group, opts)
return
end
- opts = opts or {}
- local priority = opts.priority or vim.highlight.priorities.semantic_tokens + 3
+ local priority = opts and opts.priority or vim.hl.priorities.semantic_tokens + 3
- vim.api.nvim_buf_set_extmark(bufnr, state.namespace, token.line, token.start_col, {
- hl_group = hl_group,
- end_col = token.end_col,
- priority = priority,
- strict = false,
- })
+ set_mark(bufnr, state.namespace, token, hl_group, priority)
end
--- |lsp-handler| for the method `workspace/semanticTokens/refresh`