aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/lua/vim/lsp.lua39
1 files changed, 35 insertions, 4 deletions
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 7df0064b6b..fb08e54dfc 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -306,7 +306,6 @@ local function once(fn)
end
end
-
local changetracking = {}
do
--@private
@@ -327,6 +326,7 @@ do
if not state then
state = {
pending_changes = {};
+ last_flush = {};
use_incremental_sync = (
if_nil(client.config.flags.allow_incremental_sync, true)
and client.resolved_capabilities.text_document_did_change == protocol.TextDocumentSyncKind.Incremental
@@ -347,8 +347,11 @@ do
function changetracking.reset_buf(client, bufnr)
changetracking.flush(client)
local state = state_by_client[client.id]
- if state and state.buffers then
- state.buffers[bufnr] = nil
+ if state then
+ if state.buffers then
+ state.buffers[bufnr] = nil
+ end
+ state.last_flush = {}
end
end
@@ -362,6 +365,33 @@ do
end
---@private
+ --
+ -- Adjust debounce time by taking time of last didChange notification into
+ -- consideration. If the last didChange happened more than `debounce` time ago,
+ -- debounce can be skipped and otherwise maybe reduced.
+ --
+ -- This turns the debounce into a kind of client rate limiting
+ local function next_debounce(debounce, state, bufnr)
+ if debounce == 0 then
+ return 0
+ end
+ local ns_to_ms = 0.000001
+ local last_flush = state.last_flush[bufnr]
+ if not last_flush then
+ return debounce
+ end
+ local now = uv.hrtime()
+ local ms_since_last_flush = (now - last_flush) * ns_to_ms
+ local remaining_debounce = debounce - ms_since_last_flush
+ if remaining_debounce > 0 then
+ return remaining_debounce
+ else
+ state.last_flush[bufnr] = now
+ return 0
+ end
+ end
+
+ ---@private
function changetracking.prepare(bufnr, firstline, lastline, new_lastline)
local incremental_changes = function(client)
local cached_buffers = state_by_client[client.id].buffers
@@ -383,7 +413,7 @@ do
return
end
local state = state_by_client[client.id]
- local debounce = client.config.flags.debounce_text_changes or 150
+ local debounce = next_debounce(client.config.flags.debounce_text_changes or 150, state, bufnr)
if debounce == 0 then
local changes = state.use_incremental_sync and incremental_changes(client) or full_changes()
client.notify("textDocument/didChange", {
@@ -406,6 +436,7 @@ do
end
state.pending_change = function()
state.pending_change = nil
+ state.last_flush[bufnr] = uv.hrtime()
if client.is_stopped() or not vim.api.nvim_buf_is_valid(bufnr) then
return
end