fix(lsp): account for changedtick version gap on modified reset (#29170)

Follow up to https://github.com/neovim/neovim/pull/28943
Fixes https://github.com/neovim/neovim/issues/29163
This commit is contained in:
Mathias Fußenegger
2024-06-04 17:21:37 +02:00
committed by GitHub
parent b66106a46c
commit 2e6d295f79
2 changed files with 16 additions and 13 deletions

View File

@ -502,6 +502,11 @@ function M.apply_text_document_edit(text_document_edit, index, offset_encoding)
should_check_version = false should_check_version = false
end end
-- changedtick increases on save but server only receives version updates
-- on line changes (via didChange)
-- This allows a gap of 1 to account for the servers outdated view
local version_offset = vim.b[bufnr].modified and 0 or 1
-- `VersionedTextDocumentIdentifier`s version may be null -- `VersionedTextDocumentIdentifier`s version may be null
-- https://microsoft.github.io/language-server-protocol/specification#versionedTextDocumentIdentifier -- https://microsoft.github.io/language-server-protocol/specification#versionedTextDocumentIdentifier
if if
@ -509,7 +514,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 vim.b[bufnr].changedtick > text_document.version and vim.b[bufnr].changedtick > (text_document.version + version_offset)
) )
then then
print('Buffer ', text_document.uri, ' newer than edits.') print('Buffer ', text_document.uri, ' newer than edits.')

View File

@ -2133,15 +2133,13 @@ describe('LSP', function()
}, buf_lines(target_bufnr)) }, buf_lines(target_bufnr))
end) end)
it('skips the edit if the version of the edit is behind the local buffer ', function() it('skips the edit if the version of the edit is behind the local buffer ', function()
local apply_edit_mocking_current_version = function(edit, versionedBuf) local apply_edit_mocking_current_version = function(edit)
exec_lua( exec_lua(
[[ [[
local args = {...} local args = {...}
local versionedBuf = args[2]
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
versionedBuf
) )
end end
@ -2153,17 +2151,17 @@ describe('LSP', function()
eq(baseText, buf_lines(target_bufnr)) eq(baseText, buf_lines(target_bufnr))
-- Apply an edit for an old version, should skip -- Apply an edit for an old version, should skip
apply_edit_mocking_current_version( apply_edit_mocking_current_version(text_document_edit(1))
text_document_edit(2),
{ currentVersion = 7, bufnr = target_bufnr }
)
eq(baseText, buf_lines(target_bufnr)) -- no change eq(baseText, buf_lines(target_bufnr)) -- no change
-- Sanity check that next version to current does apply change -- Sanity check that next version to current does apply change
apply_edit_mocking_current_version( apply_edit_mocking_current_version(text_document_edit(exec_lua(
text_document_edit(8), [[
{ currentVersion = 7, bufnr = target_bufnr } local bufnr = ...
) return vim.b[bufnr].changedtick
]],
target_bufnr
)))
eq({ eq({
'First ↥ 🤦 🦄 line of text', 'First ↥ 🤦 🦄 line of text',
'2nd line of 语text', '2nd line of 语text',