diff --git a/doc/nvim-tree-lua.txt b/doc/nvim-tree-lua.txt index 89ac4e722ca..060227f8220 100644 --- a/doc/nvim-tree-lua.txt +++ b/doc/nvim-tree-lua.txt @@ -527,7 +527,7 @@ Following is the default configuration. See |nvim-tree-opts| for details. >lua enable = false, show_on_dirs = false, show_on_open_dirs = true, - debounce_delay = 50, + debounce_delay = 500, severity = { min = vim.diagnostic.severity.HINT, max = vim.diagnostic.severity.ERROR, @@ -1272,7 +1272,7 @@ Enable/disable the feature. *nvim-tree.diagnostics.debounce_delay* Idle milliseconds between diagnostic event and update. - Type: `number`, Default: `50` (ms) + Type: `number`, Default: `500` (ms) *nvim-tree.diagnostics.show_on_dirs* Show diagnostic icons on parent directories. diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index 4d72d1859df..212d4c14bab 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -208,16 +208,16 @@ local function setup_autocommands(opts) if opts.diagnostics.enable then create_nvim_tree_autocmd("DiagnosticChanged", { - callback = function() + callback = function(ev) log.line("diagnostics", "DiagnosticChanged") - require("nvim-tree.diagnostics").update() + require("nvim-tree.diagnostics").update_lsp(ev) end, }) create_nvim_tree_autocmd("User", { pattern = "CocDiagnosticChange", callback = function() log.line("diagnostics", "CocDiagnosticChange") - require("nvim-tree.diagnostics").update() + require("nvim-tree.diagnostics").update_coc() end, }) end @@ -386,7 +386,7 @@ local DEFAULT_OPTS = { -- BEGIN_DEFAULT_OPTS enable = false, show_on_dirs = false, show_on_open_dirs = true, - debounce_delay = 50, + debounce_delay = 500, severity = { min = vim.diagnostic.severity.HINT, max = vim.diagnostic.severity.ERROR, diff --git a/lua/nvim-tree/diagnostics.lua b/lua/nvim-tree/diagnostics.lua index 8e84ac6c4e5..e18b992f1e0 100644 --- a/lua/nvim-tree/diagnostics.lua +++ b/lua/nvim-tree/diagnostics.lua @@ -17,7 +17,7 @@ local COC_SEVERITY_LEVELS = { } ---Absolute Node path to LSP severity level ----@alias NodeSeverities table +---@alias NodeSeverities table ---@class DiagStatus ---@field value lsp.DiagnosticSeverity|nil @@ -37,33 +37,6 @@ local function uniformize_path(path) return utils.canonical_path(path:gsub("\\", "/")) 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 ---@param severity lsp.DiagnosticSeverity ---@param config table @@ -135,11 +108,8 @@ local function from_cache(node) for bufname, severity in pairs(NODE_SEVERITIES) do local node_contains_buf = vim.startswith(bufname, nodepath .. "/") if node_contains_buf then - if severity == M.severity.max then + if not max_severity or severity < max_severity then max_severity = severity - break - else - max_severity = math.min(max_severity or severity, severity) end end end @@ -147,23 +117,68 @@ local function from_cache(node) return { value = max_severity, cache_version = NODE_SEVERITIES_VERSION } 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 -function M.update() +function M.update_coc() if not M.enable then return end - utils.debounce("diagnostics", M.debounce_delay, function() - local profile = log.profile_start("diagnostics update") - if is_using_coc() then - NODE_SEVERITIES = from_coc() - else - NODE_SEVERITIES = from_nvim_lsp() - end + utils.debounce("CocDiagnosticChanged update", M.debounce_delay, function() + local profile = log.profile_start("CocDiagnosticChanged update") + NODE_SEVERITIES = from_coc() NODE_SEVERITIES_VERSION = NODE_SEVERITIES_VERSION + 1 if log.enabled("diagnostics") then 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 log.profile_end(profile)