refactor(lsp): replace util.buf_versions with changedtick (#28943)

`lsp.util.buf_versions` was already derived from changedtick (`on_lines`
from `buf_attach` synced the version)

As far as I can tell there is no need to keep track of the state in a
separate table.
This commit is contained in:
Mathias Fußenegger
2024-05-30 10:46:26 +02:00
committed by GitHub
parent b2bad0ac91
commit 5c33815448
10 changed files with 52 additions and 57 deletions

View File

@ -22,6 +22,9 @@ API
LUA LUA
- vim.region() Use |getregionpos()| instead. - vim.region() Use |getregionpos()| instead.
LSP
- *vim.lsp.util.buf_versions* Use |b:changedtick| instead.
DIAGNOSTICS DIAGNOSTICS
- *vim.diagnostic.goto_next()* Use |vim.diagnostic.jump()| with `{count = 1}` instead. - *vim.diagnostic.goto_next()* Use |vim.diagnostic.jump()| with `{count = 1}` instead.
- *vim.diagnostic.goto_prev()* Use |vim.diagnostic.jump()| with `{count = -1}` instead. - *vim.diagnostic.goto_prev()* Use |vim.diagnostic.jump()| with `{count = -1}` instead.

View File

@ -484,7 +484,6 @@ local function text_document_did_save_handler(bufnr)
text = lsp._buf_get_full_text(bufnr), text = lsp._buf_get_full_text(bufnr),
}, },
}) })
util.buf_versions[bufnr] = 0
end end
local save_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'save') local save_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'save')
if save_capability then if save_capability then
@ -520,7 +519,6 @@ local function buf_detach_client(bufnr, client)
end end
client.attached_buffers[bufnr] = nil client.attached_buffers[bufnr] = nil
util.buf_versions[bufnr] = nil
local namespace = lsp.diagnostic.get_namespace(client.id) local namespace = lsp.diagnostic.get_namespace(client.id)
vim.diagnostic.reset(namespace, bufnr) vim.diagnostic.reset(namespace, bufnr)
@ -576,12 +574,11 @@ local function buf_attach(bufnr)
}) })
-- First time, so attach and set up stuff. -- First time, so attach and set up stuff.
api.nvim_buf_attach(bufnr, false, { api.nvim_buf_attach(bufnr, false, {
on_lines = function(_, _, changedtick, firstline, lastline, new_lastline) on_lines = function(_, _, _, firstline, lastline, new_lastline)
if #lsp.get_clients({ bufnr = bufnr }) == 0 then if #lsp.get_clients({ bufnr = bufnr }) == 0 then
-- detach if there are no clients -- detach if there are no clients
return #lsp.get_clients({ bufnr = bufnr, _uninitialized = true }) == 0 return #lsp.get_clients({ bufnr = bufnr, _uninitialized = true }) == 0
end end
util.buf_versions[bufnr] = changedtick
changetracking.send_changes(bufnr, firstline, lastline, new_lastline) changetracking.send_changes(bufnr, firstline, lastline, new_lastline)
end, end,

View File

@ -1,6 +1,5 @@
local protocol = require('vim.lsp.protocol') local protocol = require('vim.lsp.protocol')
local sync = require('vim.lsp.sync') local sync = require('vim.lsp.sync')
local util = require('vim.lsp.util')
local api = vim.api local api = vim.api
local uv = vim.uv local uv = vim.uv
@ -277,7 +276,7 @@ local function send_changes(bufnr, sync_kind, state, buf_state)
client.notify(protocol.Methods.textDocument_didChange, { client.notify(protocol.Methods.textDocument_didChange, {
textDocument = { textDocument = {
uri = uri, uri = uri,
version = util.buf_versions[bufnr], version = vim.b[bufnr].changedtick,
}, },
contentChanges = changes, contentChanges = changes,
}) })

View File

@ -673,8 +673,8 @@ function Client:_request(method, params, handler, bufnr)
end end
-- Ensure pending didChange notifications are sent so that the server doesn't operate on a stale state -- Ensure pending didChange notifications are sent so that the server doesn't operate on a stale state
changetracking.flush(self, bufnr) changetracking.flush(self, bufnr)
local version = lsp.util.buf_versions[bufnr]
bufnr = resolve_bufnr(bufnr) bufnr = resolve_bufnr(bufnr)
local version = vim.b[bufnr].changedtick
log.debug(self._log_prefix, 'client.request', self.id, method, params, handler, bufnr) log.debug(self._log_prefix, 'client.request', self.id, method, params, handler, bufnr)
local success, request_id = self.rpc.request(method, params, function(err, result) local success, request_id = self.rpc.request(method, params, function(err, result)
local context = { local context = {
@ -922,14 +922,13 @@ function Client:_text_document_did_open_handler(bufnr)
local params = { local params = {
textDocument = { textDocument = {
version = 0, version = vim.b[bufnr].changedtick,
uri = vim.uri_from_bufnr(bufnr), uri = vim.uri_from_bufnr(bufnr),
languageId = self.get_language_id(bufnr, filetype), languageId = self.get_language_id(bufnr, filetype),
text = lsp._buf_get_full_text(bufnr), text = lsp._buf_get_full_text(bufnr),
}, },
} }
self.notify(ms.textDocument_didOpen, params) self.notify(ms.textDocument_didOpen, params)
lsp.util.buf_versions[bufnr] = params.textDocument.version
-- Next chance we get, we should re-do the diagnostics -- Next chance we get, we should re-do the diagnostics
vim.schedule(function() vim.schedule(function()

View File

@ -43,7 +43,7 @@ function M.on_inlayhint(err, result, ctx, _)
return return
end end
local bufnr = assert(ctx.bufnr) local bufnr = assert(ctx.bufnr)
if util.buf_versions[bufnr] ~= ctx.version then if vim.b[bufnr].changedtick ~= ctx.version then
return return
end end
local client_id = ctx.client_id local client_id = ctx.client_id
@ -324,7 +324,7 @@ api.nvim_set_decoration_provider(namespace, {
return return
end end
if bufstate.version ~= util.buf_versions[bufnr] then if bufstate.version ~= vim.b[bufnr].changedtick then
return return
end end

View File

@ -116,7 +116,7 @@ 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]) coroutine.resume(co, vim.b[bufnr].changedtick)
end) end)
if request.version ~= coroutine.yield() then if request.version ~= coroutine.yield() then
-- request became stale since the last time the coroutine ran. -- request became stale since the last time the coroutine ran.
@ -275,7 +275,7 @@ end
--- ---
---@package ---@package
function STHighlighter:send_request() function STHighlighter:send_request()
local version = util.buf_versions[self.bufnr] local version = vim.b[self.bufnr].changedtick
self:reset_timer() self:reset_timer()
@ -418,7 +418,7 @@ end
function STHighlighter:on_win(topline, botline) function STHighlighter:on_win(topline, botline)
for client_id, state in pairs(self.client_state) do for client_id, state in pairs(self.client_state) do
local current_result = state.current_result local current_result = state.current_result
if current_result.version and current_result.version == util.buf_versions[self.bufnr] then if current_result.version and current_result.version == vim.b[self.bufnr].changedtick then
if not current_result.namespace_cleared then if not current_result.namespace_cleared then
api.nvim_buf_clear_namespace(self.bufnr, state.namespace, 0, -1) api.nvim_buf_clear_namespace(self.bufnr, state.namespace, 0, -1)
current_result.namespace_cleared = true current_result.namespace_cleared = true

View File

@ -509,8 +509,7 @@ function M.apply_text_document_edit(text_document_edit, index, offset_encoding)
and ( and (
text_document.version text_document.version
and text_document.version > 0 and text_document.version > 0
and M.buf_versions[bufnr] and vim.b[bufnr].changedtick > text_document.version
and M.buf_versions[bufnr] > text_document.version
) )
then then
print('Buffer ', text_document.uri, ' newer than edits.') print('Buffer ', text_document.uri, ' newer than edits.')
@ -2200,9 +2199,16 @@ function M._refresh(method, opts)
end end
end end
---@nodoc
---@deprecated
---@type table<integer,integer>
M.buf_versions = setmetatable({}, {
__index = function(_, bufnr)
vim.deprecate('vim.lsp.util.buf_versions', 'vim.b.changedtick', '0.13')
return vim.b[bufnr].changedtick
end,
})
M._get_line_byte_from_position = get_line_byte_from_position M._get_line_byte_from_position = get_line_byte_from_position
---@nodoc
M.buf_versions = {} ---@type table<integer,integer>
return M return M

View File

@ -471,7 +471,7 @@ function tests.basic_check_buffer_open()
languageId = '', languageId = '',
text = table.concat({ 'testing', '123' }, '\n') .. '\n', text = table.concat({ 'testing', '123' }, '\n') .. '\n',
uri = 'file://', uri = 'file://',
version = 0, version = 2,
}, },
}) })
expect_notification('finish') expect_notification('finish')
@ -498,7 +498,7 @@ function tests.basic_check_buffer_open_and_change()
languageId = '', languageId = '',
text = table.concat({ 'testing', '123' }, '\n') .. '\n', text = table.concat({ 'testing', '123' }, '\n') .. '\n',
uri = 'file://', uri = 'file://',
version = 0, version = 2,
}, },
}) })
expect_notification('textDocument/didChange', { expect_notification('textDocument/didChange', {
@ -534,7 +534,7 @@ function tests.basic_check_buffer_open_and_change_noeol()
languageId = '', languageId = '',
text = table.concat({ 'testing', '123' }, '\n'), text = table.concat({ 'testing', '123' }, '\n'),
uri = 'file://', uri = 'file://',
version = 0, version = 2,
}, },
}) })
expect_notification('textDocument/didChange', { expect_notification('textDocument/didChange', {
@ -569,7 +569,7 @@ function tests.basic_check_buffer_open_and_change_multi()
languageId = '', languageId = '',
text = table.concat({ 'testing', '123' }, '\n') .. '\n', text = table.concat({ 'testing', '123' }, '\n') .. '\n',
uri = 'file://', uri = 'file://',
version = 0, version = 2,
}, },
}) })
expect_notification('textDocument/didChange', { expect_notification('textDocument/didChange', {
@ -614,7 +614,7 @@ function tests.basic_check_buffer_open_and_change_multi_and_close()
languageId = '', languageId = '',
text = table.concat({ 'testing', '123' }, '\n') .. '\n', text = table.concat({ 'testing', '123' }, '\n') .. '\n',
uri = 'file://', uri = 'file://',
version = 0, version = 2,
}, },
}) })
expect_notification('textDocument/didChange', { expect_notification('textDocument/didChange', {
@ -672,7 +672,7 @@ function tests.basic_check_buffer_open_and_change_incremental()
languageId = '', languageId = '',
text = table.concat({ 'testing', '123' }, '\n') .. '\n', text = table.concat({ 'testing', '123' }, '\n') .. '\n',
uri = 'file://', uri = 'file://',
version = 0, version = 2,
}, },
}) })
expect_notification('textDocument/didChange', { expect_notification('textDocument/didChange', {
@ -715,7 +715,7 @@ function tests.basic_check_buffer_open_and_change_incremental_editing()
languageId = '', languageId = '',
text = table.concat({ 'testing', '123' }, '\n'), text = table.concat({ 'testing', '123' }, '\n'),
uri = 'file://', uri = 'file://',
version = 0, version = 2,
}, },
}) })
expect_notification('textDocument/didChange', { expect_notification('textDocument/didChange', {

View File

@ -111,6 +111,7 @@ describe('semantic token highlighting', function()
end) end)
it('buffer is highlighted when attached', function() it('buffer is highlighted when attached', function()
insert(text)
exec_lua([[ exec_lua([[
bufnr = vim.api.nvim_get_current_buf() bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_win_set_buf(0, bufnr) vim.api.nvim_win_set_buf(0, bufnr)
@ -118,8 +119,6 @@ describe('semantic token highlighting', function()
client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd }) client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
]]) ]])
insert(text)
screen:expect { screen:expect {
grid = [[ grid = [[
#include <iostream> | #include <iostream> |
@ -141,6 +140,7 @@ describe('semantic token highlighting', function()
end) end)
it('use LspTokenUpdate and highlight_token', function() it('use LspTokenUpdate and highlight_token', function()
insert(text)
exec_lua([[ exec_lua([[
vim.api.nvim_create_autocmd("LspTokenUpdate", { vim.api.nvim_create_autocmd("LspTokenUpdate", {
callback = function(args) callback = function(args)
@ -157,8 +157,6 @@ describe('semantic token highlighting', function()
client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd }) client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
]]) ]])
insert(text)
screen:expect { screen:expect {
grid = [[ grid = [[
#include <iostream> | #include <iostream> |
@ -180,14 +178,17 @@ describe('semantic token highlighting', function()
end) end)
it('buffer is unhighlighted when client is detached', function() it('buffer is unhighlighted when client is detached', function()
insert(text)
exec_lua([[ exec_lua([[
bufnr = vim.api.nvim_get_current_buf() bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_win_set_buf(0, bufnr) vim.api.nvim_win_set_buf(0, bufnr)
client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd }) client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
vim.wait(1000, function()
return #server.messages > 1
end)
]]) ]])
insert(text)
exec_lua([[ exec_lua([[
vim.notify = function() end vim.notify = function() end
vim.lsp.buf_detach_client(bufnr, client_id) vim.lsp.buf_detach_client(bufnr, client_id)
@ -331,14 +332,13 @@ describe('semantic token highlighting', function()
end) end)
it('buffer is re-highlighted when force refreshed', function() it('buffer is re-highlighted when force refreshed', function()
insert(text)
exec_lua([[ exec_lua([[
bufnr = vim.api.nvim_get_current_buf() bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_win_set_buf(0, bufnr) vim.api.nvim_win_set_buf(0, bufnr)
client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd }) client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
]]) ]])
insert(text)
screen:expect { screen:expect {
grid = [[ grid = [[
#include <iostream> | #include <iostream> |
@ -412,13 +412,14 @@ describe('semantic token highlighting', function()
end) end)
it('updates highlights with delta request on buffer change', function() it('updates highlights with delta request on buffer change', function()
insert(text)
exec_lua([[ exec_lua([[
bufnr = vim.api.nvim_get_current_buf() bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_win_set_buf(0, bufnr) vim.api.nvim_win_set_buf(0, bufnr)
client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd }) client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
]]) ]])
insert(text)
screen:expect { screen:expect {
grid = [[ grid = [[
#include <iostream> | #include <iostream> |
@ -597,6 +598,7 @@ describe('semantic token highlighting', function()
end) end)
it('does not send delta requests if not supported by server', function() it('does not send delta requests if not supported by server', function()
insert(text)
exec_lua( exec_lua(
[[ [[
local legend, response, edit_response = ... local legend, response, edit_response = ...
@ -625,7 +627,6 @@ describe('semantic token highlighting', function()
edit_response edit_response
) )
insert(text)
screen:expect { screen:expect {
grid = [[ grid = [[
#include <iostream> | #include <iostream> |
@ -1449,6 +1450,7 @@ int main()
}, },
}) do }) do
it(test.it, function() it(test.it, function()
insert(test.text1)
exec_lua(create_server_definition) exec_lua(create_server_definition)
exec_lua( exec_lua(
[[ [[
@ -1485,8 +1487,6 @@ int main()
test.response2 test.response2
) )
insert(test.text1)
test.expected_screen1() test.expected_screen1()
local highlights = exec_lua([[ local highlights = exec_lua([[

View File

@ -255,7 +255,7 @@ describe('LSP', function()
return return
end end
local expected_handlers = { local expected_handlers = {
{ NIL, {}, { method = 'shutdown', bufnr = 1, client_id = 1 } }, { NIL, {}, { method = 'shutdown', bufnr = 1, client_id = 1, version = 2 } },
{ NIL, {}, { method = 'test', client_id = 1 } }, { NIL, {}, { method = 'test', client_id = 1 } },
} }
test_rpc_server { test_rpc_server {
@ -948,7 +948,11 @@ describe('LSP', function()
it('should forward ContentModified to callback', function() it('should forward ContentModified to callback', function()
local expected_handlers = { local expected_handlers = {
{ NIL, {}, { method = 'finish', client_id = 1 } }, { NIL, {}, { method = 'finish', client_id = 1 } },
{ { code = -32801 }, NIL, { method = 'error_code_test', bufnr = 1, client_id = 1 } }, {
{ code = -32801 },
NIL,
{ method = 'error_code_test', bufnr = 1, client_id = 1, version = 2 },
},
} }
local client --- @type vim.lsp.Client local client --- @type vim.lsp.Client
test_rpc_server { test_rpc_server {
@ -978,7 +982,7 @@ 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 } }, { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1, version = 2 } },
} }
local client --- @type vim.lsp.Client local client --- @type vim.lsp.Client
test_rpc_server { test_rpc_server {
@ -1045,7 +1049,7 @@ 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 } }, { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1, version = 2 } },
} }
local client --- @type vim.lsp.Client local client --- @type vim.lsp.Client
test_rpc_server { test_rpc_server {
@ -1084,7 +1088,7 @@ 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 } }, { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1, version = 2 } },
} }
local client --- @type vim.lsp.Client local client --- @type vim.lsp.Client
test_rpc_server { test_rpc_server {
@ -1364,6 +1368,7 @@ describe('LSP', function()
}, },
bufnr = 2, bufnr = 2,
client_id = 1, client_id = 1,
version = 2,
}, },
}, },
{ NIL, {}, { method = 'start', client_id = 1 } }, { NIL, {}, { method = 'start', client_id = 1 } },
@ -2117,7 +2122,6 @@ describe('LSP', function()
local args = {...} local args = {...}
local bufnr = select(1, ...) local bufnr = select(1, ...)
local text_edit = select(2, ...) local text_edit = select(2, ...)
vim.lsp.util.buf_versions[bufnr] = 10
vim.lsp.util.apply_text_document_edit(text_edit, nil, 'utf-16') vim.lsp.util.apply_text_document_edit(text_edit, nil, 'utf-16')
]], ]],
target_bufnr, target_bufnr,
@ -2134,7 +2138,6 @@ describe('LSP', function()
[[ [[
local args = {...} local args = {...}
local versionedBuf = args[2] local versionedBuf = args[2]
vim.lsp.util.buf_versions[versionedBuf.bufnr] = versionedBuf.currentVersion
vim.lsp.util.apply_text_document_edit(args[1], nil, 'utf-16') vim.lsp.util.apply_text_document_edit(args[1], nil, 'utf-16')
]], ]],
edit, edit,
@ -2239,18 +2242,6 @@ describe('LSP', function()
} }
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
local update_changed_tick = function()
vim.lsp.util.buf_versions[bufnr] = vim.api.nvim_buf_get_var(bufnr, 'changedtick')
end
update_changed_tick()
vim.api.nvim_buf_attach(bufnr, false, {
on_changedtick = function()
update_changed_tick()
end
})
return {bufnr, vim.api.nvim_buf_get_var(bufnr, 'changedtick')} return {bufnr, vim.api.nvim_buf_get_var(bufnr, 'changedtick')}
]] ]]