lsp: fix bug when documentEdit version=null for unattached buffer (#12272)

This commit is contained in:
landerlo
2020-05-14 04:14:52 +01:00
committed by GitHub
parent 55b62a937c
commit 02155f5c10
2 changed files with 49 additions and 57 deletions

View File

@@ -168,11 +168,13 @@ end
function M.apply_text_document_edit(text_document_edit) function M.apply_text_document_edit(text_document_edit)
local text_document = text_document_edit.textDocument local text_document = text_document_edit.textDocument
local bufnr = vim.uri_to_bufnr(text_document.uri) local bufnr = vim.uri_to_bufnr(text_document.uri)
-- `VersionedTextDocumentIdentifier`s version may be nil https://microsoft.github.io/language-server-protocol/specification#versionedTextDocumentIdentifier if text_document.version then
if text_document.version ~= vim.NIL and M.buf_versions[bufnr] > text_document.version then -- `VersionedTextDocumentIdentifier`s version may be null https://microsoft.github.io/language-server-protocol/specification#versionedTextDocumentIdentifier
if text_document.version ~= vim.NIL and M.buf_versions[bufnr] ~= nil and M.buf_versions[bufnr] > text_document.version then
print("Buffer ", text_document.uri, " newer than edits.") print("Buffer ", text_document.uri, " newer than edits.")
return return
end end
end
M.apply_text_edits(text_document_edit.edits, bufnr) M.apply_text_edits(text_document_edit.edits, bufnr)
end end

View File

@@ -835,33 +835,30 @@ describe('LSP', function()
describe('apply_text_document_edit', function() describe('apply_text_document_edit', function()
local target_bufnr local target_bufnr
local text_document_edit = function(editVersion)
return {
edits = {
make_edit(0, 0, 0, 3, "First ↥ 🤦 🦄")
},
textDocument = {
uri = "file://fake/uri";
version = editVersion
}
}
end
before_each(function() before_each(function()
target_bufnr = exec_lua [[ target_bufnr = exec_lua [[
local bufnr = vim.fn.bufadd("fake/uri") local bufnr = vim.uri_to_bufnr("file://fake/uri")
local lines = {"1st line of text", "2nd line of text"} local lines = {"1st line of text", "2nd line of text"}
vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines) vim.api.nvim_buf_set_lines(bufnr, 0, 1, false, lines)
return bufnr return bufnr
]] ]]
end) end)
it('correctly goes ahead with the edit if all is normal', function() it('correctly goes ahead with the edit if all is normal', function()
local text_document_edit = { exec_lua('vim.lsp.util.apply_text_document_edit(...)', text_document_edit(5))
edits = {
make_edit(0, 0, 0, 3, "First")
},
textDocument = {
uri = "file://fake/uri";
version = 5
}
}
exec_lua([[
local args = {...}
local target_bufnr = args[2]
vim.lsp.util.buf_versions[target_bufnr] = 4
vim.lsp.util.apply_text_document_edit(...)
]], text_document_edit, target_bufnr)
eq({ eq({
'First line of text'; 'First ↥ 🤦 🦄 line of text';
'2nd line of text'; '2nd line of text';
}, buf_lines(target_bufnr)) }, buf_lines(target_bufnr))
end) end)
it('correctly goes ahead with the edit if the version is vim.NIL', function() it('correctly goes ahead with the edit if the version is vim.NIL', function()
@@ -871,45 +868,38 @@ describe('LSP', function()
]] ]]
eq(json.b, exec_lua("return vim.NIL")) eq(json.b, exec_lua("return vim.NIL"))
local text_document_edit = { exec_lua('vim.lsp.util.apply_text_document_edit(...)', text_document_edit(exec_lua("return vim.NIL")))
edits = {
make_edit(0, 0, 0, 3, "First")
},
textDocument = {
uri = "file://fake/uri";
version = exec_lua("return vim.NIL")
}
}
exec_lua([[
local args = {...}
local target_bufnr = args[2]
vim.lsp.util.buf_versions[target_bufnr] = vim.NIL
vim.lsp.util.apply_text_document_edit(...)
]], text_document_edit, target_bufnr)
eq({ eq({
'First line of text'; 'First ↥ 🤦 🦄 line of text';
'2nd line of text'; '2nd line of text';
}, 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 text_document_edit = { local apply_edit_mocking_current_version = function(edit, versionedBuf)
edits = {
make_edit(0, 0, 0, 3, "First")
},
textDocument = {
uri = "file://fake/uri";
version = 1
}
}
exec_lua([[ exec_lua([[
local args = {...} local args = {...}
local target_bufnr = args[2] local versionedBuf = args[2]
vim.lsp.util.buf_versions[target_bufnr] = 2 vim.lsp.util.buf_versions[versionedBuf.bufnr] = versionedBuf.currentVersion
vim.lsp.util.apply_text_document_edit(...) vim.lsp.util.apply_text_document_edit(...)
]], text_document_edit, target_bufnr) ]], edit, versionedBuf)
eq({ end
local baseText = {
'1st line of text'; '1st line of text';
'2nd line of text'; '2nd line of text';
}
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})
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})
eq({
'First ↥ 🤦 🦄 line of text';
'2nd line of 语text';
}, buf_lines(target_bufnr)) }, buf_lines(target_bufnr))
end) end)
end) end)