lsp: Fix text edits with the same start position (#12434)

According to the LSP spec[1], multiple edits can have the same starting
position, and if that is the case, they should be applied in the order
as they come in the array.

The implementation uses a reverse sort to not interfere with non applied
edits, but failed to take into account the spec.

[1] https://microsoft.github.io/language-server-protocol/specifications/specification-3-14/#textedit
This commit is contained in:
Andreas Johansson 2020-06-14 21:23:16 +02:00 committed by GitHub
parent a0a84fc9e0
commit 44fe8828f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 25 additions and 2 deletions

View File

@ -92,7 +92,7 @@ local function sort_by_key(fn)
end
end
local edit_sort_key = sort_by_key(function(e)
return {e.A[1], e.A[2], e.i}
return {e.A[1], e.A[2], -e.i}
end)
--- Position is a https://microsoft.github.io/language-server-protocol/specifications/specification-current/#position

View File

@ -811,10 +811,33 @@ describe('LSP', function()
'å å ɧ 汉语 ↥ 🤦 🦄';
}, buf_lines(1))
end)
it('handles edits with the same start position, applying changes in the order in the array', function()
local edits = {
make_edit(0, 6, 0, 10, {""});
make_edit(0, 6, 0, 6, {"REPLACE"});
make_edit(1, 0, 1, 3, {""});
make_edit(1, 0, 1, 0, {"123"});
make_edit(2, 16, 2, 18, {""});
make_edit(2, 16, 2, 16, {"XYZ"});
make_edit(3, 7, 3, 11, {"this"});
make_edit(3, 7, 3, 11, {"will"});
make_edit(3, 7, 3, 11, {"not "});
make_edit(3, 7, 3, 11, {"show"});
make_edit(3, 7, 3, 11, {"(but this will)"});
}
exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1)
eq({
'First REPLACE of text';
'123ond line of text';
'Third line of teXYZ';
'Fourth (but this will) of text';
'å å ɧ 汉语 ↥ 🤦 🦄';
}, buf_lines(1))
end)
it('applies complex edits', function()
local edits = {
make_edit(0, 0, 0, 0, {"", "12"});
make_edit(0, 0, 0, 0, {"3", "foo"});
make_edit(0, 0, 0, 0, {"", "12"});
make_edit(0, 1, 0, 1, {"bar", "123"});
make_edit(0, #"First ", 0, #"First line of text", {"guy"});
make_edit(1, 0, 1, #'Second', {"baz"});