diff options
author | Michael Lingelbach <m.j.lbach@gmail.com> | 2021-11-15 08:51:30 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-15 08:51:30 -0800 |
commit | 87a053f126c79f5eeb1654e35beb31d9fe733163 (patch) | |
tree | bdfbe6fbbd03f391561b7e9884b376fd606e04ec | |
parent | 8f984dc1f29aa6ce41f233b983453bfd795e8238 (diff) | |
download | rneovim-87a053f126c79f5eeb1654e35beb31d9fe733163.tar.gz rneovim-87a053f126c79f5eeb1654e35beb31d9fe733163.tar.bz2 rneovim-87a053f126c79f5eeb1654e35beb31d9fe733163.zip |
fix(lsp): fix edge cases in incremental sync (#16308)
-rw-r--r-- | runtime/lua/vim/lsp/sync.lua | 8 | ||||
-rw-r--r-- | test/functional/plugin/lsp/incremental_sync_spec.lua | 150 |
2 files changed, 116 insertions, 42 deletions
diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua index 37247c61b9..585c14a00f 100644 --- a/runtime/lua/vim/lsp/sync.lua +++ b/runtime/lua/vim/lsp/sync.lua @@ -219,6 +219,10 @@ local function compute_end_range(prev_lines, curr_lines, start_range, firstline, -- Iterate from end to beginning of shortest line local prev_end_byte_idx = prev_line_length - byte_offset + 1 + -- Handle case where lines match + if prev_end_byte_idx == 0 then + prev_end_byte_idx = 1 + end local prev_byte_idx, prev_char_idx = align_position(prev_line, prev_end_byte_idx, 'start', offset_encoding) local prev_end_range = { line_idx = prev_line_idx, byte_idx = prev_byte_idx, char_idx = prev_char_idx } @@ -228,6 +232,10 @@ local function compute_end_range(prev_lines, curr_lines, start_range, firstline, curr_end_range = { line_idx = start_line_idx, byte_idx = 1, char_idx = 1 } else local curr_end_byte_idx = curr_line_length - byte_offset + 1 + -- Handle case where lines match + if curr_end_byte_idx == 0 then + curr_end_byte_idx = 1 + end local curr_byte_idx, curr_char_idx = align_position(curr_line, curr_end_byte_idx, 'start', offset_encoding) curr_end_range = { line_idx = curr_line_idx, byte_idx = curr_byte_idx, char_idx = curr_char_idx } end diff --git a/test/functional/plugin/lsp/incremental_sync_spec.lua b/test/functional/plugin/lsp/incremental_sync_spec.lua index fe4f8f3593..890db4abf5 100644 --- a/test/functional/plugin/lsp/incremental_sync_spec.lua +++ b/test/functional/plugin/lsp/incremental_sync_spec.lua @@ -66,6 +66,7 @@ local function test_edit(prev_buffer, edit_operations, expected_text_changes, of exec_lua("test_unreg = 'test1'") end + describe('incremental synchronization', function() describe('single line edit', function() it('inserting a character in an empty buffer', function() @@ -163,54 +164,119 @@ describe('incremental synchronization', function() } test_edit({"a"}, {"rb"}, expected_text_changes, 'utf-16', '\n') end) - describe('multi-byte edits', function() - it('join and undo', function() - local expected_text_changes = { - { - range = { - ['start'] = { - character = 11, - line = 0 - }, - ['end'] = { - character = 11, - line = 0 - } + end) + + describe('multi-operation edits', function() + it('mult-line substitution', function() + local expected_text_changes = { + { + range = { + ["end"] = { + character = 11, + line = 2 }, + ["start"] = { + character = 10, + line = 2 } }, + rangeLength = 1, + text = '', + },{ + range = { + ["end"] = { + character = 10, + line = 2 }, + start = { + character = 10, + line = 2 } }, + rangeLength = 0, + text = '2', + },{ + range = { + ["end"] = { + character = 11, + line = 3 }, + ["start"] = { + character = 10, + line = 3 } }, + rangeLength = 1, + text = '' + },{ + range = { + ['end'] = { + character = 10, + line = 3 }, + ['start'] = { + character = 10, + line = 3 } }, + rangeLength = 0, + text = '3' }, + { + range = { + ['end'] = { + character = 0, + line = 3 }, + ['start'] = { + character = 12, + line = 2 } }, + rangeLength = 1, + text = '\n' + } + } + local original_lines = { + "\\begin{document}", + "\\section*{1}", + "\\section*{1}", + "\\section*{1}", + "\\end{document}" + } + test_edit(original_lines, {"3gg$h<C-V>jg<C-A>"}, expected_text_changes, 'utf-16', '\n') + end) + it('join and undo', function() + local expected_text_changes = { + { + range = { + ['start'] = { + character = 11, + line = 0 }, - rangeLength = 0, - text = ' test3' - },{ - range = { - ['start'] = { - character = 0, - line = 1 - }, - ['end'] = { - character = 0, - line = 2 - } + ['end'] = { + character = 11, + line = 0 + } + }, + rangeLength = 0, + text = ' test3' + },{ + range = { + ['start'] = { + character = 0, + line = 1 }, - rangeLength = 6, - text = '' - },{ - range = { - ['start'] = { - character = 11, - line = 0 - }, - ['end'] = { - character = 17, - line = 0 - } + ['end'] = { + character = 0, + line = 2 + } + }, + rangeLength = 6, + text = '' + },{ + range = { + ['start'] = { + character = 11, + line = 0 }, - rangeLength = 6, - text = '\ntest3' + ['end'] = { + character = 17, + line = 0 + } }, - } - test_edit({"test1 test2", "test3"}, {"J", "u"}, expected_text_changes, 'utf-16', '\n') - end) + rangeLength = 6, + text = '\ntest3' + }, + } + test_edit({"test1 test2", "test3"}, {"J", "u"}, expected_text_changes, 'utf-16', '\n') end) end) + describe('multi-byte edits', function() it('deleting a multibyte character', function() local expected_text_changes = { |