fix(#2954): more efficient LSP updates, increase diagnostics.debounce_delay from 50ms to 500ms (#3007)
* fix(#2954): use LSP diagnostic data deltas from events instead of a full query * fix(#2954): use LSP diagnostic data deltas from events instead of a full query
This commit is contained in:
parent
f7c65e11d6
commit
1f3ffd6af1
@ -527,7 +527,7 @@ Following is the default configuration. See |nvim-tree-opts| for details. >lua
|
|||||||
enable = false,
|
enable = false,
|
||||||
show_on_dirs = false,
|
show_on_dirs = false,
|
||||||
show_on_open_dirs = true,
|
show_on_open_dirs = true,
|
||||||
debounce_delay = 50,
|
debounce_delay = 500,
|
||||||
severity = {
|
severity = {
|
||||||
min = vim.diagnostic.severity.HINT,
|
min = vim.diagnostic.severity.HINT,
|
||||||
max = vim.diagnostic.severity.ERROR,
|
max = vim.diagnostic.severity.ERROR,
|
||||||
@ -1272,7 +1272,7 @@ Enable/disable the feature.
|
|||||||
|
|
||||||
*nvim-tree.diagnostics.debounce_delay*
|
*nvim-tree.diagnostics.debounce_delay*
|
||||||
Idle milliseconds between diagnostic event and update.
|
Idle milliseconds between diagnostic event and update.
|
||||||
Type: `number`, Default: `50` (ms)
|
Type: `number`, Default: `500` (ms)
|
||||||
|
|
||||||
*nvim-tree.diagnostics.show_on_dirs*
|
*nvim-tree.diagnostics.show_on_dirs*
|
||||||
Show diagnostic icons on parent directories.
|
Show diagnostic icons on parent directories.
|
||||||
|
|||||||
@ -208,16 +208,16 @@ local function setup_autocommands(opts)
|
|||||||
|
|
||||||
if opts.diagnostics.enable then
|
if opts.diagnostics.enable then
|
||||||
create_nvim_tree_autocmd("DiagnosticChanged", {
|
create_nvim_tree_autocmd("DiagnosticChanged", {
|
||||||
callback = function()
|
callback = function(ev)
|
||||||
log.line("diagnostics", "DiagnosticChanged")
|
log.line("diagnostics", "DiagnosticChanged")
|
||||||
require("nvim-tree.diagnostics").update()
|
require("nvim-tree.diagnostics").update_lsp(ev)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
create_nvim_tree_autocmd("User", {
|
create_nvim_tree_autocmd("User", {
|
||||||
pattern = "CocDiagnosticChange",
|
pattern = "CocDiagnosticChange",
|
||||||
callback = function()
|
callback = function()
|
||||||
log.line("diagnostics", "CocDiagnosticChange")
|
log.line("diagnostics", "CocDiagnosticChange")
|
||||||
require("nvim-tree.diagnostics").update()
|
require("nvim-tree.diagnostics").update_coc()
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
@ -386,7 +386,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS
|
|||||||
enable = false,
|
enable = false,
|
||||||
show_on_dirs = false,
|
show_on_dirs = false,
|
||||||
show_on_open_dirs = true,
|
show_on_open_dirs = true,
|
||||||
debounce_delay = 50,
|
debounce_delay = 500,
|
||||||
severity = {
|
severity = {
|
||||||
min = vim.diagnostic.severity.HINT,
|
min = vim.diagnostic.severity.HINT,
|
||||||
max = vim.diagnostic.severity.ERROR,
|
max = vim.diagnostic.severity.ERROR,
|
||||||
|
|||||||
@ -17,7 +17,7 @@ local COC_SEVERITY_LEVELS = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
---Absolute Node path to LSP severity level
|
---Absolute Node path to LSP severity level
|
||||||
---@alias NodeSeverities table<string, lsp.DiagnosticSeverity>
|
---@alias NodeSeverities table<string, vim.diagnostic.Severity>
|
||||||
|
|
||||||
---@class DiagStatus
|
---@class DiagStatus
|
||||||
---@field value lsp.DiagnosticSeverity|nil
|
---@field value lsp.DiagnosticSeverity|nil
|
||||||
@ -37,33 +37,6 @@ local function uniformize_path(path)
|
|||||||
return utils.canonical_path(path:gsub("\\", "/"))
|
return utils.canonical_path(path:gsub("\\", "/"))
|
||||||
end
|
end
|
||||||
|
|
||||||
---Marshal severities from LSP. Does nothing when LSP disabled.
|
|
||||||
---@return NodeSeverities
|
|
||||||
local function from_nvim_lsp()
|
|
||||||
local buffer_severity = {}
|
|
||||||
|
|
||||||
-- is_enabled is not present in all 0.10 builds/releases, see #2781
|
|
||||||
local is_enabled = false
|
|
||||||
if vim.fn.has("nvim-0.10") == 1 and type(vim.diagnostic.is_enabled) == "function" then
|
|
||||||
is_enabled = vim.diagnostic.is_enabled()
|
|
||||||
elseif type(vim.diagnostic.is_disabled) == "function" then ---@diagnostic disable-line: deprecated
|
|
||||||
is_enabled = not vim.diagnostic.is_disabled() ---@diagnostic disable-line: deprecated
|
|
||||||
end
|
|
||||||
|
|
||||||
if is_enabled then
|
|
||||||
for _, diagnostic in ipairs(vim.diagnostic.get(nil, { severity = M.severity })) do
|
|
||||||
if diagnostic.severity and diagnostic.bufnr and vim.api.nvim_buf_is_valid(diagnostic.bufnr) then
|
|
||||||
local bufname = uniformize_path(vim.api.nvim_buf_get_name(diagnostic.bufnr))
|
|
||||||
if not buffer_severity[bufname] or diagnostic.severity < buffer_severity[bufname] then
|
|
||||||
buffer_severity[bufname] = diagnostic.severity
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return buffer_severity
|
|
||||||
end
|
|
||||||
|
|
||||||
---Severity is within diagnostics.severity.min, diagnostics.severity.max
|
---Severity is within diagnostics.severity.min, diagnostics.severity.max
|
||||||
---@param severity lsp.DiagnosticSeverity
|
---@param severity lsp.DiagnosticSeverity
|
||||||
---@param config table
|
---@param config table
|
||||||
@ -135,11 +108,8 @@ local function from_cache(node)
|
|||||||
for bufname, severity in pairs(NODE_SEVERITIES) do
|
for bufname, severity in pairs(NODE_SEVERITIES) do
|
||||||
local node_contains_buf = vim.startswith(bufname, nodepath .. "/")
|
local node_contains_buf = vim.startswith(bufname, nodepath .. "/")
|
||||||
if node_contains_buf then
|
if node_contains_buf then
|
||||||
if severity == M.severity.max then
|
if not max_severity or severity < max_severity then
|
||||||
max_severity = severity
|
max_severity = severity
|
||||||
break
|
|
||||||
else
|
|
||||||
max_severity = math.min(max_severity or severity, severity)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -147,23 +117,68 @@ local function from_cache(node)
|
|||||||
return { value = max_severity, cache_version = NODE_SEVERITIES_VERSION }
|
return { value = max_severity, cache_version = NODE_SEVERITIES_VERSION }
|
||||||
end
|
end
|
||||||
|
|
||||||
---Fired on DiagnosticChanged and CocDiagnosticChanged events:
|
---Fired on DiagnosticChanged for a single buffer.
|
||||||
|
---This will be called on set and reset of diagnostics.
|
||||||
|
---On disabling LSP, a reset event will be sent for all buffers.
|
||||||
|
---@param ev table standard event with data.diagnostics populated
|
||||||
|
function M.update_lsp(ev)
|
||||||
|
if not M.enable or not ev or not ev.data or not ev.data.diagnostics then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local profile_event = log.profile_start("DiagnosticChanged event")
|
||||||
|
|
||||||
|
---@type vim.Diagnostic[]
|
||||||
|
local diagnostics = ev.data.diagnostics
|
||||||
|
|
||||||
|
-- use the buffer from the event, as ev.data.diagnostics will be empty on resolved diagnostics
|
||||||
|
local bufname = uniformize_path(vim.api.nvim_buf_get_name(ev.buf))
|
||||||
|
|
||||||
|
---@type vim.diagnostic.Severity?
|
||||||
|
local new_severity = nil
|
||||||
|
|
||||||
|
-- most severe (lowest) severity in user range
|
||||||
|
for _, diagnostic in ipairs(diagnostics) do
|
||||||
|
if diagnostic.severity >= M.severity.max and diagnostic.severity <= M.severity.min then
|
||||||
|
if not new_severity or diagnostic.severity < new_severity then
|
||||||
|
new_severity = diagnostic.severity
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- record delta and schedule a redraw
|
||||||
|
if new_severity ~= NODE_SEVERITIES[bufname] then
|
||||||
|
NODE_SEVERITIES[bufname] = new_severity
|
||||||
|
NODE_SEVERITIES_VERSION = NODE_SEVERITIES_VERSION + 1
|
||||||
|
|
||||||
|
utils.debounce("DiagnosticChanged redraw", M.debounce_delay, function()
|
||||||
|
local profile_redraw = log.profile_start("DiagnosticChanged redraw")
|
||||||
|
|
||||||
|
local explorer = core.get_explorer()
|
||||||
|
if explorer then
|
||||||
|
explorer.renderer:draw()
|
||||||
|
end
|
||||||
|
|
||||||
|
log.profile_end(profile_redraw)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
log.profile_end(profile_event)
|
||||||
|
end
|
||||||
|
|
||||||
|
---Fired on CocDiagnosticChanged events:
|
||||||
---debounced retrieval, cache update, version increment and draw
|
---debounced retrieval, cache update, version increment and draw
|
||||||
function M.update()
|
function M.update_coc()
|
||||||
if not M.enable then
|
if not M.enable then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
utils.debounce("diagnostics", M.debounce_delay, function()
|
utils.debounce("CocDiagnosticChanged update", M.debounce_delay, function()
|
||||||
local profile = log.profile_start("diagnostics update")
|
local profile = log.profile_start("CocDiagnosticChanged update")
|
||||||
if is_using_coc() then
|
NODE_SEVERITIES = from_coc()
|
||||||
NODE_SEVERITIES = from_coc()
|
|
||||||
else
|
|
||||||
NODE_SEVERITIES = from_nvim_lsp()
|
|
||||||
end
|
|
||||||
NODE_SEVERITIES_VERSION = NODE_SEVERITIES_VERSION + 1
|
NODE_SEVERITIES_VERSION = NODE_SEVERITIES_VERSION + 1
|
||||||
if log.enabled("diagnostics") then
|
if log.enabled("diagnostics") then
|
||||||
for bufname, severity in pairs(NODE_SEVERITIES) do
|
for bufname, severity in pairs(NODE_SEVERITIES) do
|
||||||
log.line("diagnostics", "Indexing bufname '%s' with severity %d", bufname, severity)
|
log.line("diagnostics", "COC Indexing bufname '%s' with severity %d", bufname, severity)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
log.profile_end(profile)
|
log.profile_end(profile)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user