mirror of
https://github.com/neovim/neovim.git
synced 2025-10-21 17:21:49 +00:00
fix(lsp): rewrite incremental sync (#16252)
* use codeunits/points instead of byte ranges when applicable * take into account different file formats when computing range and sending text (dos, unix, and mac supported) * add tests of incremental sync
This commit is contained in:

committed by
GitHub

parent
953ae71fd3
commit
2ecf0a4c61
@@ -5,6 +5,7 @@ local log = require 'vim.lsp.log'
|
||||
local lsp_rpc = require 'vim.lsp.rpc'
|
||||
local protocol = require 'vim.lsp.protocol'
|
||||
local util = require 'vim.lsp.util'
|
||||
local sync = require 'vim.lsp.sync'
|
||||
|
||||
local vim = vim
|
||||
local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_buf_get_option
|
||||
@@ -108,6 +109,12 @@ local valid_encodings = {
|
||||
UTF8 = 'utf-8'; UTF16 = 'utf-16'; UTF32 = 'utf-32';
|
||||
}
|
||||
|
||||
local format_line_ending = {
|
||||
["unix"] = '\n',
|
||||
["dos"] = '\r\n',
|
||||
["mac"] = '\r',
|
||||
}
|
||||
|
||||
local client_index = 0
|
||||
---@private
|
||||
--- Returns a new, unused client id.
|
||||
@@ -351,15 +358,14 @@ do
|
||||
end
|
||||
end
|
||||
|
||||
function changetracking.prepare(bufnr, firstline, new_lastline, changedtick)
|
||||
function changetracking.prepare(bufnr, firstline, lastline, new_lastline, changedtick)
|
||||
local incremental_changes = function(client)
|
||||
local cached_buffers = state_by_client[client.id].buffers
|
||||
local lines = nvim_buf_get_lines(bufnr, 0, -1, true)
|
||||
local startline = math.min(firstline + 1, math.min(#cached_buffers[bufnr], #lines))
|
||||
local endline = math.min(-(#lines - new_lastline), -1)
|
||||
local incremental_change = vim.lsp.util.compute_diff(
|
||||
cached_buffers[bufnr], lines, startline, endline, client.offset_encoding or 'utf-16')
|
||||
cached_buffers[bufnr] = lines
|
||||
local curr_lines = nvim_buf_get_lines(bufnr, 0, -1, true)
|
||||
local line_ending = format_line_ending[vim.api.nvim_buf_get_option(0, 'fileformat')]
|
||||
local incremental_change = sync.compute_diff(
|
||||
cached_buffers[bufnr], curr_lines, firstline, lastline, new_lastline, client.offset_encoding or 'utf-16', line_ending or '\n')
|
||||
cached_buffers[bufnr] = curr_lines
|
||||
return incremental_change
|
||||
end
|
||||
local full_changes = once(function()
|
||||
@@ -1067,22 +1073,14 @@ end
|
||||
--- Notify all attached clients that a buffer has changed.
|
||||
local text_document_did_change_handler
|
||||
do
|
||||
text_document_did_change_handler = function(_, bufnr, changedtick,
|
||||
firstline, lastline, new_lastline, old_byte_size, old_utf32_size,
|
||||
old_utf16_size)
|
||||
|
||||
local _ = log.debug() and log.debug(
|
||||
string.format("on_lines bufnr: %s, changedtick: %s, firstline: %s, lastline: %s, new_lastline: %s, old_byte_size: %s, old_utf32_size: %s, old_utf16_size: %s",
|
||||
bufnr, changedtick, firstline, lastline, new_lastline, old_byte_size, old_utf32_size, old_utf16_size),
|
||||
nvim_buf_get_lines(bufnr, firstline, new_lastline, true)
|
||||
)
|
||||
text_document_did_change_handler = function(_, bufnr, changedtick, firstline, lastline, new_lastline)
|
||||
|
||||
-- Don't do anything if there are no clients attached.
|
||||
if tbl_isempty(all_buffer_active_clients[bufnr] or {}) then
|
||||
return
|
||||
end
|
||||
util.buf_versions[bufnr] = changedtick
|
||||
local compute_change_and_notify = changetracking.prepare(bufnr, firstline, new_lastline, changedtick)
|
||||
local compute_change_and_notify = changetracking.prepare(bufnr, firstline, lastline, new_lastline, changedtick)
|
||||
for_each_buffer_client(bufnr, compute_change_and_notify)
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user