Skip to content

Commit

Permalink
fix(lsp): account for changedtick version gap on modified reset (#29170)
Browse files Browse the repository at this point in the history
Follow up to #28943
Fixes #29163
  • Loading branch information
mfussenegger committed Jun 4, 2024
1 parent b66106a commit 2e6d295
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 13 deletions.
7 changes: 6 additions & 1 deletion runtime/lua/vim/lsp/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -502,14 +502,19 @@ function M.apply_text_document_edit(text_document_edit, index, offset_encoding)
should_check_version = false
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
-- https://microsoft.github.io/language-server-protocol/specification#versionedTextDocumentIdentifier
if
should_check_version
and (
text_document.version
and text_document.version > 0
and vim.b[bufnr].changedtick > text_document.version
and vim.b[bufnr].changedtick > (text_document.version + version_offset)
)
then
print('Buffer ', text_document.uri, ' newer than edits.')
Expand Down
22 changes: 10 additions & 12 deletions test/functional/plugin/lsp_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2133,15 +2133,13 @@ describe('LSP', function()
}, buf_lines(target_bufnr))
end)
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(
[[
local args = {...}
local versionedBuf = args[2]
vim.lsp.util.apply_text_document_edit(args[1], nil, 'utf-16')
]],
edit,
versionedBuf
edit
)
end

Expand All @@ -2153,17 +2151,17 @@ describe('LSP', function()
eq(baseText, buf_lines(target_bufnr))

-- Apply an edit for an old version, should skip
apply_edit_mocking_current_version(
text_document_edit(2),
{ currentVersion = 7, bufnr = target_bufnr }
)
apply_edit_mocking_current_version(text_document_edit(1))
eq(baseText, buf_lines(target_bufnr)) -- no change

-- Sanity check that next version to current does apply change
apply_edit_mocking_current_version(
text_document_edit(8),
{ currentVersion = 7, bufnr = target_bufnr }
)
apply_edit_mocking_current_version(text_document_edit(exec_lua(
[[
local bufnr = ...
return vim.b[bufnr].changedtick
]],
target_bufnr
)))
eq({
'First ↥ 🤦 🦄 line of text',
'2nd line of 语text',
Expand Down

0 comments on commit 2e6d295

Please sign in to comment.