aboutsummaryrefslogtreecommitdiff
path: root/runtime/lua/vim/lsp/sync.lua
diff options
context:
space:
mode:
authorJaehwang Jung <tomtomjhj@gmail.com>2024-07-31 23:18:24 +0900
committerGitHub <noreply@github.com>2024-07-31 16:18:24 +0200
commit6bb40f3dbffb4b9858d9b13486d1832db8f51755 (patch)
treee23791d44d85f18c9e85e17d981c995636481a3b /runtime/lua/vim/lsp/sync.lua
parent4e90bc30237ae81bf15e77c17ac8089a2cc74046 (diff)
downloadrneovim-6bb40f3dbffb4b9858d9b13486d1832db8f51755.tar.gz
rneovim-6bb40f3dbffb4b9858d9b13486d1832db8f51755.tar.bz2
rneovim-6bb40f3dbffb4b9858d9b13486d1832db8f51755.zip
fix(lsp): prevent desync due to empty buffer (#29904)
Problem: Some language servers (e.g., rust-analyzer, texlab) are desynced when the user deletes the entire contents of the buffer. This is due to the discrepancy between how nvim computes diff and how nvim treats empty buffer. * diff: If the buffer became empty, then the diff includes the last line's eol. * empty buffer: Even if the buffer is empty, nvim regards it as having a single empty line with eol. Solution: Add special case for diff computation when the buffer becomes empty so that it does not include the eol of the last line.
Diffstat (limited to 'runtime/lua/vim/lsp/sync.lua')
-rw-r--r--runtime/lua/vim/lsp/sync.lua13
1 files changed, 12 insertions, 1 deletions
diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua
index 936579e003..bdfe8d51b8 100644
--- a/runtime/lua/vim/lsp/sync.lua
+++ b/runtime/lua/vim/lsp/sync.lua
@@ -212,7 +212,8 @@ end
---@param lastline integer
---@param new_lastline integer
---@param offset_encoding string
----@return vim.lsp.sync.Range, vim.lsp.sync.Range
+---@return vim.lsp.sync.Range prev_end_range
+---@return vim.lsp.sync.Range curr_end_range
local function compute_end_range(
prev_lines,
curr_lines,
@@ -222,6 +223,16 @@ local function compute_end_range(
new_lastline,
offset_encoding
)
+ -- A special case for the following `firstline == new_lastline` case where lines are deleted.
+ -- Even if the buffer has become empty, nvim behaves as if it has an empty line with eol.
+ if #curr_lines == 1 and curr_lines[1] == '' then
+ local prev_line = prev_lines[lastline - 1]
+ return {
+ line_idx = lastline - 1,
+ byte_idx = #prev_line + 1,
+ char_idx = compute_line_length(prev_line, offset_encoding) + 1,
+ }, { line_idx = 1, byte_idx = 1, char_idx = 1 }
+ end
-- If firstline == new_lastline, the first change occurred on a line that was deleted.
-- In this case, the last_byte...
if firstline == new_lastline then