mirror of
https://github.com/neovim/neovim.git
synced 2026-04-21 06:45:37 +00:00
feat(lsp): semantic token range improvements #37451
* cache all tokens from various range requests for a given document
version
- all new token highlights are merged with previous highlights to
maintain order and the "marked" property
- this allows the tokens to stop flickering once they've loaded once
per document version
* abandon the processing coroutine if the request_id has changed instead
of relying only on the document version
- this will improve efficiency if a new range request is made while a
previous one was processing its result
* apply new highlights from processing coroutine directly to the current
result when the version hasn't changed
- this allows new highlights to be immediately drawable once they've
processed instead of waiting for the whole response to be processed
at once
* rpc layer was changed to provide the request ID back in success
callbacks, which is then provided as a request_id field on the handler
context to lsp handlers
This commit is contained in:
@@ -2436,7 +2436,7 @@ Lua module: vim.lsp.rpc *lsp-rpc*
|
|||||||
Client RPC object
|
Client RPC object
|
||||||
|
|
||||||
Fields: ~
|
Fields: ~
|
||||||
• {request} (`fun(method: string, params: table?, callback: fun(err?: lsp.ResponseError, result: any), notify_reply_callback?: fun(message_id: integer)):boolean,integer?`)
|
• {request} (`fun(method: string, params: table?, callback: fun(err?: lsp.ResponseError, result: any, request_id: integer), notify_reply_callback?: fun(message_id: integer)):boolean,integer?`)
|
||||||
See |vim.lsp.rpc.request()|
|
See |vim.lsp.rpc.request()|
|
||||||
• {notify} (`fun(method: string, params: any): boolean`) See
|
• {notify} (`fun(method: string, params: any): boolean`) See
|
||||||
|vim.lsp.rpc.notify()|
|
|vim.lsp.rpc.notify()|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ error('Cannot require a meta file')
|
|||||||
---@class lsp.HandlerContext
|
---@class lsp.HandlerContext
|
||||||
---@field method vim.lsp.protocol.Method
|
---@field method vim.lsp.protocol.Method
|
||||||
---@field client_id integer
|
---@field client_id integer
|
||||||
|
---@field request_id? integer
|
||||||
---@field bufnr? integer
|
---@field bufnr? integer
|
||||||
---@field params? any
|
---@field params? any
|
||||||
---@field version? integer
|
---@field version? integer
|
||||||
|
|||||||
@@ -731,10 +731,11 @@ function Client:request(method, params, handler, bufnr)
|
|||||||
local request_registered = false
|
local request_registered = false
|
||||||
|
|
||||||
-- NOTE: rpc.request might call an in-process (Lua) server, thus may be synchronous.
|
-- NOTE: rpc.request might call an in-process (Lua) server, thus may be synchronous.
|
||||||
local success, request_id = self.rpc.request(method, params, function(err, result)
|
local success, request_id = self.rpc.request(method, params, function(err, result, request_id)
|
||||||
handler(err, result, {
|
handler(err, result, {
|
||||||
method = method,
|
method = method,
|
||||||
client_id = self.id,
|
client_id = self.id,
|
||||||
|
request_id = request_id,
|
||||||
bufnr = bufnr,
|
bufnr = bufnr,
|
||||||
params = params,
|
params = params,
|
||||||
version = version,
|
version = version,
|
||||||
@@ -896,7 +897,7 @@ function Client:stop(force)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Sending a signal after a process has exited is acceptable.
|
-- Sending a signal after a process has exited is acceptable.
|
||||||
rpc.request('shutdown', nil, function(err, _)
|
rpc.request('shutdown', nil, function(err, _, _)
|
||||||
if err == nil then
|
if err == nil then
|
||||||
rpc.notify('exit')
|
rpc.notify('exit')
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ end
|
|||||||
---
|
---
|
||||||
---@param method vim.lsp.protocol.Method The invoked LSP method
|
---@param method vim.lsp.protocol.Method The invoked LSP method
|
||||||
---@param params table? Parameters for the invoked LSP method
|
---@param params table? Parameters for the invoked LSP method
|
||||||
---@param callback fun(err?: lsp.ResponseError, result: any) Callback to invoke
|
---@param callback fun(err?: lsp.ResponseError, result: any, message_id: integer) Callback to invoke
|
||||||
---@param notify_reply_callback? fun(message_id: integer) Callback to invoke as soon as a request is no longer pending
|
---@param notify_reply_callback? fun(message_id: integer) Callback to invoke as soon as a request is no longer pending
|
||||||
---@return boolean success `true` if request could be sent, `false` if not
|
---@return boolean success `true` if request could be sent, `false` if not
|
||||||
---@return integer? message_id if request could be sent, `nil` if not
|
---@return integer? message_id if request could be sent, `nil` if not
|
||||||
@@ -467,7 +467,8 @@ function Client:handle_body(body)
|
|||||||
M.client_errors.SERVER_RESULT_CALLBACK_ERROR,
|
M.client_errors.SERVER_RESULT_CALLBACK_ERROR,
|
||||||
callback,
|
callback,
|
||||||
decoded.error,
|
decoded.error,
|
||||||
decoded.result ~= vim.NIL and decoded.result or nil
|
decoded.result ~= vim.NIL and decoded.result or nil,
|
||||||
|
result_id
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
self:on_error(M.client_errors.NO_RESULT_CALLBACK_FOUND, decoded)
|
self:on_error(M.client_errors.NO_RESULT_CALLBACK_FOUND, decoded)
|
||||||
@@ -505,7 +506,7 @@ end
|
|||||||
--- @class vim.lsp.rpc.PublicClient
|
--- @class vim.lsp.rpc.PublicClient
|
||||||
---
|
---
|
||||||
--- See [vim.lsp.rpc.request()]
|
--- See [vim.lsp.rpc.request()]
|
||||||
--- @field request fun(method: vim.lsp.protocol.Method.ClientToServer.Request, params: table?, callback: fun(err?: lsp.ResponseError, result: any), notify_reply_callback?: fun(message_id: integer)):boolean,integer?
|
--- @field request fun(method: vim.lsp.protocol.Method.ClientToServer.Request, params: table?, callback: fun(err?: lsp.ResponseError, result: any, request_id: integer), notify_reply_callback?: fun(message_id: integer)):boolean,integer?
|
||||||
---
|
---
|
||||||
--- See [vim.lsp.rpc.notify()]
|
--- See [vim.lsp.rpc.notify()]
|
||||||
--- @field notify fun(method: vim.lsp.protocol.Method.ClientToServer.Notification, params: any): boolean
|
--- @field notify fun(method: vim.lsp.protocol.Method.ClientToServer.Notification, params: any): boolean
|
||||||
|
|||||||
@@ -77,8 +77,9 @@ end
|
|||||||
---@param bufnr integer
|
---@param bufnr integer
|
||||||
---@param client vim.lsp.Client
|
---@param client vim.lsp.Client
|
||||||
---@param request STActiveRequest
|
---@param request STActiveRequest
|
||||||
|
---@param ranges STTokenRange[]
|
||||||
---@return STTokenRange[]
|
---@return STTokenRange[]
|
||||||
local function tokens_to_ranges(data, bufnr, client, request)
|
local function tokens_to_ranges(data, bufnr, client, request, ranges)
|
||||||
local legend = client.server_capabilities.semanticTokensProvider.legend
|
local legend = client.server_capabilities.semanticTokensProvider.legend
|
||||||
local token_types = legend.tokenTypes
|
local token_types = legend.tokenTypes
|
||||||
local token_modifiers = legend.tokenModifiers
|
local token_modifiers = legend.tokenModifiers
|
||||||
@@ -86,7 +87,9 @@ local function tokens_to_ranges(data, bufnr, client, request)
|
|||||||
local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||||
-- For all encodings, \r\n takes up two code points, and \n (or \r) takes up one.
|
-- For all encodings, \r\n takes up two code points, and \n (or \r) takes up one.
|
||||||
local eol_offset = vim.bo.fileformat[bufnr] == 'dos' and 2 or 1
|
local eol_offset = vim.bo.fileformat[bufnr] == 'dos' and 2 or 1
|
||||||
local ranges = {} ---@type STTokenRange[]
|
local version = request.version
|
||||||
|
local request_id = request.request_id
|
||||||
|
local last_insert_idx = 1
|
||||||
|
|
||||||
local start = uv.hrtime()
|
local start = uv.hrtime()
|
||||||
local ms_to_ns = 1e6
|
local ms_to_ns = 1e6
|
||||||
@@ -102,14 +105,18 @@ local function tokens_to_ranges(data, bufnr, client, request)
|
|||||||
|
|
||||||
if elapsed_ns > yield_interval_ns then
|
if elapsed_ns > yield_interval_ns then
|
||||||
vim.schedule(function()
|
vim.schedule(function()
|
||||||
coroutine.resume(co, util.buf_versions[bufnr])
|
-- Ensure the request hasn't become stale since the last time the coroutine ran.
|
||||||
|
-- If it's stale, we don't resume the coroutine so it'll be garbage collected.
|
||||||
|
if
|
||||||
|
version == util.buf_versions[bufnr]
|
||||||
|
and request_id == request.request_id
|
||||||
|
and api.nvim_buf_is_valid(bufnr)
|
||||||
|
then
|
||||||
|
coroutine.resume(co)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
if request.version ~= coroutine.yield() then
|
|
||||||
-- request became stale since the last time the coroutine ran.
|
|
||||||
-- abandon it by yielding without a way to resume
|
|
||||||
coroutine.yield()
|
|
||||||
end
|
|
||||||
|
|
||||||
|
coroutine.yield()
|
||||||
start = uv.hrtime()
|
start = uv.hrtime()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -141,7 +148,8 @@ local function tokens_to_ranges(data, bufnr, client, request)
|
|||||||
|
|
||||||
local end_col = vim.str_byteindex(buf_line, encoding, end_char, false)
|
local end_col = vim.str_byteindex(buf_line, encoding, end_char, false)
|
||||||
|
|
||||||
ranges[#ranges + 1] = {
|
---@type STTokenRange
|
||||||
|
local range = {
|
||||||
line = line,
|
line = line,
|
||||||
end_line = end_line,
|
end_line = end_line,
|
||||||
start_col = start_col,
|
start_col = start_col,
|
||||||
@@ -150,6 +158,47 @@ local function tokens_to_ranges(data, bufnr, client, request)
|
|||||||
modifiers = modifiers,
|
modifiers = modifiers,
|
||||||
marked = false,
|
marked = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if last_insert_idx <= #ranges then
|
||||||
|
local needs_insert = true
|
||||||
|
local idx = vim.list.bisect(ranges, { line = range.line }, {
|
||||||
|
lo = last_insert_idx,
|
||||||
|
key = function(highlight)
|
||||||
|
return highlight.line
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
while idx <= #ranges do
|
||||||
|
local token = ranges[idx]
|
||||||
|
|
||||||
|
if
|
||||||
|
token.line > range.line
|
||||||
|
or (token.line == range.line and token.start_col > range.start_col)
|
||||||
|
then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
if
|
||||||
|
range.line == token.line
|
||||||
|
and range.start_col == token.start_col
|
||||||
|
and range.end_line == token.end_line
|
||||||
|
and range.end_col == token.end_col
|
||||||
|
and range.type == token.type
|
||||||
|
then
|
||||||
|
needs_insert = false
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
idx = idx + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
last_insert_idx = idx
|
||||||
|
if needs_insert then
|
||||||
|
table.insert(ranges, last_insert_idx, range)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
last_insert_idx = #ranges + 1
|
||||||
|
ranges[last_insert_idx] = range
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -207,7 +256,8 @@ function STHighlighter:cancel_active_request(client_id)
|
|||||||
if state.active_request.request_id then
|
if state.active_request.request_id then
|
||||||
local client = assert(vim.lsp.get_client_by_id(client_id))
|
local client = assert(vim.lsp.get_client_by_id(client_id))
|
||||||
client:cancel_request(state.active_request.request_id)
|
client:cancel_request(state.active_request.request_id)
|
||||||
state.active_request = {}
|
state.active_request.request_id = nil
|
||||||
|
state.active_request.version = nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -274,8 +324,8 @@ function STHighlighter:send_request()
|
|||||||
-- cancel stale in-flight request
|
-- cancel stale in-flight request
|
||||||
if active_request.request_id then
|
if active_request.request_id then
|
||||||
client:cancel_request(active_request.request_id)
|
client:cancel_request(active_request.request_id)
|
||||||
active_request = {}
|
active_request.request_id = nil
|
||||||
state.active_request = active_request
|
active_request.version = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
---@type lsp.SemanticTokensParams|lsp.SemanticTokensRangeParams|lsp.SemanticTokensDeltaParams
|
---@type lsp.SemanticTokensParams|lsp.SemanticTokensRangeParams|lsp.SemanticTokensDeltaParams
|
||||||
@@ -301,11 +351,18 @@ function STHighlighter:send_request()
|
|||||||
end
|
end
|
||||||
|
|
||||||
if err or not response then
|
if err or not response then
|
||||||
highlighter.client_state[client.id].active_request = {}
|
active_request.request_id = nil
|
||||||
|
active_request.version = nil
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
coroutine.wrap(STHighlighter.process_response)(highlighter, response, client, version)
|
coroutine.wrap(STHighlighter.process_response)(
|
||||||
|
highlighter,
|
||||||
|
response,
|
||||||
|
client,
|
||||||
|
ctx.request_id,
|
||||||
|
version
|
||||||
|
)
|
||||||
end, self.bufnr)
|
end, self.bufnr)
|
||||||
|
|
||||||
if success then
|
if success then
|
||||||
@@ -359,16 +416,17 @@ end
|
|||||||
---@async
|
---@async
|
||||||
---@param response lsp.SemanticTokens|lsp.SemanticTokensDelta
|
---@param response lsp.SemanticTokens|lsp.SemanticTokensDelta
|
||||||
---@param client vim.lsp.Client
|
---@param client vim.lsp.Client
|
||||||
|
---@param request_id integer
|
||||||
---@param version integer
|
---@param version integer
|
||||||
---@private
|
---@private
|
||||||
function STHighlighter:process_response(response, client, version)
|
function STHighlighter:process_response(response, client, request_id, version)
|
||||||
local state = self.client_state[client.id]
|
local state = self.client_state[client.id]
|
||||||
if not state then
|
if not state then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- ignore stale responses
|
-- ignore stale responses
|
||||||
if state.active_request.version and version ~= state.active_request.version then
|
if state.active_request.request_id and request_id ~= state.active_request.request_id then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -400,25 +458,32 @@ function STHighlighter:process_response(response, client, version)
|
|||||||
tokens = response.data
|
tokens = response.data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local current_result = state.current_result
|
||||||
|
local version_changed = version ~= current_result.version
|
||||||
|
local highlights = {} --- @type STTokenRange[]
|
||||||
|
if current_result.highlights and not version_changed then
|
||||||
|
highlights = assert(current_result.highlights)
|
||||||
|
end
|
||||||
|
|
||||||
-- convert token list to highlight ranges
|
-- convert token list to highlight ranges
|
||||||
-- this could yield and run over multiple event loop iterations
|
-- this could yield and run over multiple event loop iterations
|
||||||
local highlights = tokens_to_ranges(tokens, self.bufnr, client, state.active_request)
|
highlights = tokens_to_ranges(tokens, self.bufnr, client, state.active_request, highlights)
|
||||||
|
|
||||||
-- reset active request
|
-- reset active request
|
||||||
state.active_request = {}
|
state.active_request.request_id = nil
|
||||||
|
state.active_request.version = nil
|
||||||
|
|
||||||
-- update the state with the new results
|
-- update the state with the new results
|
||||||
local current_result = state.current_result
|
|
||||||
current_result.version = version
|
current_result.version = version
|
||||||
current_result.result_id = response.resultId
|
current_result.result_id = response.resultId
|
||||||
current_result.tokens = tokens
|
current_result.tokens = tokens
|
||||||
current_result.highlights = highlights
|
current_result.highlights = highlights
|
||||||
current_result.namespace_cleared = false
|
if version_changed then
|
||||||
|
current_result.namespace_cleared = false
|
||||||
-- redraw all windows displaying buffer (if still valid)
|
|
||||||
if api.nvim_buf_is_valid(self.bufnr) then
|
|
||||||
api.nvim__redraw({ buf = self.bufnr, valid = true })
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- redraw all windows displaying buffer
|
||||||
|
api.nvim__redraw({ buf = self.bufnr, valid = true })
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param bufnr integer
|
--- @param bufnr integer
|
||||||
|
|||||||
@@ -322,6 +322,182 @@ describe('semantic token highlighting', function()
|
|||||||
eq(true, called_range)
|
eq(true, called_range)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('range requests preserve highlights outside updated range', function()
|
||||||
|
screen:try_resize(40, 6)
|
||||||
|
insert(text)
|
||||||
|
feed('gg')
|
||||||
|
|
||||||
|
local small_range_response = [[{
|
||||||
|
"data": [ 2, 4, 4, 3, 8193, 2, 8, 1, 1, 1025 ]
|
||||||
|
}]]
|
||||||
|
|
||||||
|
local client_id, bufnr = exec_lua(function(l, resp)
|
||||||
|
_G.response = resp
|
||||||
|
_G.server2 = _G._create_server({
|
||||||
|
capabilities = {
|
||||||
|
semanticTokensProvider = {
|
||||||
|
range = true,
|
||||||
|
legend = vim.fn.json_decode(l),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
handlers = {
|
||||||
|
['textDocument/semanticTokens/range'] = function(_, _, callback)
|
||||||
|
callback(nil, vim.fn.json_decode(_G.response))
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
local bufnr = vim.api.nvim_get_current_buf()
|
||||||
|
local client_id = assert(vim.lsp.start({ name = 'dummy', cmd = _G.server2.cmd }))
|
||||||
|
vim.schedule(function()
|
||||||
|
vim.lsp.semantic_tokens._start(bufnr, client_id, 10)
|
||||||
|
end)
|
||||||
|
return client_id, bufnr
|
||||||
|
end, legend, small_range_response)
|
||||||
|
|
||||||
|
screen:expect {
|
||||||
|
grid = [[
|
||||||
|
^#include <iostream> |
|
||||||
|
|
|
||||||
|
int {8:main}() |
|
||||||
|
{ |
|
||||||
|
int {7:x}; |
|
||||||
|
|
|
||||||
|
]],
|
||||||
|
}
|
||||||
|
|
||||||
|
eq(
|
||||||
|
2,
|
||||||
|
exec_lua(function()
|
||||||
|
return #vim.lsp.semantic_tokens.__STHighlighter.active[bufnr].client_state[client_id].current_result.highlights
|
||||||
|
end)
|
||||||
|
)
|
||||||
|
|
||||||
|
small_range_response = [[{
|
||||||
|
"data": [ 7, 0, 5, 20, 0, 1, 0, 22, 20, 0, 1, 0, 6, 20, 0 ]
|
||||||
|
}]]
|
||||||
|
|
||||||
|
exec_lua(function(resp)
|
||||||
|
_G.response = resp
|
||||||
|
end, small_range_response)
|
||||||
|
|
||||||
|
feed('G')
|
||||||
|
|
||||||
|
screen:expect {
|
||||||
|
grid = [[
|
||||||
|
{6:#else} |
|
||||||
|
{6: printf("%d\n", x);} |
|
||||||
|
{6:#endif} |
|
||||||
|
} |
|
||||||
|
^} |
|
||||||
|
|
|
||||||
|
]],
|
||||||
|
}
|
||||||
|
|
||||||
|
eq(
|
||||||
|
5,
|
||||||
|
exec_lua(function()
|
||||||
|
return #vim.lsp.semantic_tokens.__STHighlighter.active[bufnr].client_state[client_id].current_result.highlights
|
||||||
|
end)
|
||||||
|
)
|
||||||
|
|
||||||
|
small_range_response = [[{
|
||||||
|
"data": [ 2, 4, 4, 3, 8193, 2, 8, 1, 1, 1025, 1, 7, 11, 19, 8192 ]
|
||||||
|
}]]
|
||||||
|
|
||||||
|
exec_lua(function(resp)
|
||||||
|
_G.response = resp
|
||||||
|
end, small_range_response)
|
||||||
|
feed('ggLj0')
|
||||||
|
|
||||||
|
screen:expect {
|
||||||
|
grid = [[
|
||||||
|
|
|
||||||
|
int {8:main}() |
|
||||||
|
{ |
|
||||||
|
int {7:x}; |
|
||||||
|
^#ifdef {5:__cplusplus} |
|
||||||
|
|
|
||||||
|
]],
|
||||||
|
}
|
||||||
|
|
||||||
|
eq(
|
||||||
|
6,
|
||||||
|
exec_lua(function()
|
||||||
|
return #vim.lsp.semantic_tokens.__STHighlighter.active[bufnr].client_state[client_id].current_result.highlights
|
||||||
|
end)
|
||||||
|
)
|
||||||
|
|
||||||
|
eq(
|
||||||
|
{
|
||||||
|
{
|
||||||
|
line = 2,
|
||||||
|
end_line = 2,
|
||||||
|
start_col = 4,
|
||||||
|
end_col = 8,
|
||||||
|
marked = true,
|
||||||
|
modifiers = {
|
||||||
|
declaration = true,
|
||||||
|
globalScope = true,
|
||||||
|
},
|
||||||
|
type = 'function',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
line = 4,
|
||||||
|
end_line = 4,
|
||||||
|
start_col = 8,
|
||||||
|
end_col = 9,
|
||||||
|
marked = true,
|
||||||
|
modifiers = {
|
||||||
|
declaration = true,
|
||||||
|
functionScope = true,
|
||||||
|
},
|
||||||
|
type = 'variable',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
line = 5,
|
||||||
|
end_line = 5,
|
||||||
|
start_col = 7,
|
||||||
|
end_col = 18,
|
||||||
|
marked = true,
|
||||||
|
modifiers = {
|
||||||
|
globalScope = true,
|
||||||
|
},
|
||||||
|
type = 'macro',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
line = 7,
|
||||||
|
end_line = 7,
|
||||||
|
start_col = 0,
|
||||||
|
end_col = 5,
|
||||||
|
marked = true,
|
||||||
|
modifiers = {},
|
||||||
|
type = 'comment',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
line = 8,
|
||||||
|
end_line = 8,
|
||||||
|
start_col = 0,
|
||||||
|
end_col = 22,
|
||||||
|
marked = true,
|
||||||
|
modifiers = {},
|
||||||
|
type = 'comment',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
line = 9,
|
||||||
|
end_line = 9,
|
||||||
|
start_col = 0,
|
||||||
|
end_col = 6,
|
||||||
|
marked = true,
|
||||||
|
modifiers = {},
|
||||||
|
type = 'comment',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
exec_lua(function()
|
||||||
|
return vim.lsp.semantic_tokens.__STHighlighter.active[bufnr].client_state[client_id].current_result.highlights
|
||||||
|
end)
|
||||||
|
)
|
||||||
|
end)
|
||||||
|
|
||||||
it('use LspTokenUpdate and highlight_token', function()
|
it('use LspTokenUpdate and highlight_token', function()
|
||||||
insert(text)
|
insert(text)
|
||||||
exec_lua(function()
|
exec_lua(function()
|
||||||
|
|||||||
@@ -1074,7 +1074,7 @@ describe('LSP', function()
|
|||||||
{
|
{
|
||||||
{ code = -32802 },
|
{ code = -32802 },
|
||||||
NIL,
|
NIL,
|
||||||
{ method = 'error_code_test', bufnr = 1, client_id = 1, version = 0 },
|
{ method = 'error_code_test', bufnr = 1, client_id = 1, request_id = 2, version = 0 },
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
local client --- @type vim.lsp.Client
|
local client --- @type vim.lsp.Client
|
||||||
@@ -1107,7 +1107,7 @@ describe('LSP', function()
|
|||||||
{
|
{
|
||||||
{ code = -32801 },
|
{ code = -32801 },
|
||||||
NIL,
|
NIL,
|
||||||
{ method = 'error_code_test', bufnr = 1, client_id = 1, version = 0 },
|
{ method = 'error_code_test', bufnr = 1, client_id = 1, request_id = 2, version = 0 },
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
local client --- @type vim.lsp.Client
|
local client --- @type vim.lsp.Client
|
||||||
@@ -1137,7 +1137,11 @@ describe('LSP', function()
|
|||||||
it('should track pending requests to the language server', function()
|
it('should track pending requests to the language server', function()
|
||||||
local expected_handlers = {
|
local expected_handlers = {
|
||||||
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
||||||
{ NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1, version = 0 } },
|
{
|
||||||
|
NIL,
|
||||||
|
{},
|
||||||
|
{ method = 'slow_request', bufnr = 1, client_id = 1, request_id = 2, version = 0 },
|
||||||
|
},
|
||||||
}
|
}
|
||||||
local client --- @type vim.lsp.Client
|
local client --- @type vim.lsp.Client
|
||||||
test_rpc_server {
|
test_rpc_server {
|
||||||
@@ -1212,7 +1216,11 @@ describe('LSP', function()
|
|||||||
it('should clear pending and cancel requests on reply', function()
|
it('should clear pending and cancel requests on reply', function()
|
||||||
local expected_handlers = {
|
local expected_handlers = {
|
||||||
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
||||||
{ NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1, version = 0 } },
|
{
|
||||||
|
NIL,
|
||||||
|
{},
|
||||||
|
{ method = 'slow_request', bufnr = 1, client_id = 1, request_id = 2, version = 0 },
|
||||||
|
},
|
||||||
}
|
}
|
||||||
local client --- @type vim.lsp.Client
|
local client --- @type vim.lsp.Client
|
||||||
test_rpc_server {
|
test_rpc_server {
|
||||||
@@ -1316,7 +1324,11 @@ describe('LSP', function()
|
|||||||
it('should trigger LspRequest autocmd when requests table changes', function()
|
it('should trigger LspRequest autocmd when requests table changes', function()
|
||||||
local expected_handlers = {
|
local expected_handlers = {
|
||||||
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
{ NIL, {}, { method = 'finish', client_id = 1 } },
|
||||||
{ NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1, version = 0 } },
|
{
|
||||||
|
NIL,
|
||||||
|
{},
|
||||||
|
{ method = 'slow_request', bufnr = 1, client_id = 1, request_id = 2, version = 0 },
|
||||||
|
},
|
||||||
}
|
}
|
||||||
local client --- @type vim.lsp.Client
|
local client --- @type vim.lsp.Client
|
||||||
test_rpc_server {
|
test_rpc_server {
|
||||||
@@ -1609,6 +1621,7 @@ describe('LSP', function()
|
|||||||
},
|
},
|
||||||
bufnr = 2,
|
bufnr = 2,
|
||||||
client_id = 1,
|
client_id = 1,
|
||||||
|
request_id = 2,
|
||||||
version = 0,
|
version = 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -4515,7 +4528,7 @@ describe('LSP', function()
|
|||||||
name = 'prepare_rename_placeholder',
|
name = 'prepare_rename_placeholder',
|
||||||
expected_handlers = {
|
expected_handlers = {
|
||||||
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
||||||
{ {}, NIL, { method = 'textDocument/rename', client_id = 1, bufnr = 1 } },
|
{ {}, NIL, { method = 'textDocument/rename', client_id = 1, request_id = 3, bufnr = 1 } },
|
||||||
{ NIL, {}, { method = 'start', client_id = 1 } },
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
||||||
},
|
},
|
||||||
expected_text = 'placeholder', -- see fake lsp response
|
expected_text = 'placeholder', -- see fake lsp response
|
||||||
@@ -4525,7 +4538,7 @@ describe('LSP', function()
|
|||||||
name = 'prepare_rename_range',
|
name = 'prepare_rename_range',
|
||||||
expected_handlers = {
|
expected_handlers = {
|
||||||
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
{ NIL, {}, { method = 'shutdown', client_id = 1 } },
|
||||||
{ {}, NIL, { method = 'textDocument/rename', client_id = 1, bufnr = 1 } },
|
{ {}, NIL, { method = 'textDocument/rename', client_id = 1, request_id = 3, bufnr = 1 } },
|
||||||
{ NIL, {}, { method = 'start', client_id = 1 } },
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
||||||
},
|
},
|
||||||
expected_text = 'line', -- see test case and fake lsp response
|
expected_text = 'line', -- see test case and fake lsp response
|
||||||
@@ -4653,7 +4666,7 @@ describe('LSP', function()
|
|||||||
{
|
{
|
||||||
NIL,
|
NIL,
|
||||||
{ command = 'dummy1', title = 'Command 1' },
|
{ command = 'dummy1', title = 'Command 1' },
|
||||||
{ bufnr = 1, method = 'workspace/executeCommand', client_id = 1 },
|
{ bufnr = 1, method = 'workspace/executeCommand', request_id = 3, client_id = 1 },
|
||||||
},
|
},
|
||||||
{ NIL, {}, { method = 'start', client_id = 1 } },
|
{ NIL, {}, { method = 'start', client_id = 1 } },
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user