diff --git a/lua/rulebook/diagnostic-actions.lua b/lua/rulebook/diagnostic-actions.lua index 3240033..b2d108e 100644 --- a/lua/rulebook/diagnostic-actions.lua +++ b/lua/rulebook/diagnostic-actions.lua @@ -2,26 +2,33 @@ local M = {} local notify = require("rulebook.utils").notify -------------------------------------------------------------------------------- ----checks whether rule has id and source, as prescribed in nvim diagnostic structure ---@param diag vim.Diagnostic ----@return boolean whether rule is valid +---@return boolean ---@nodiscard -local function validDiagObj(diag) +local function sourceUsesCodes(diag) local config = require("rulebook.config").config local sourcesWithNoCodes = vim.iter(config.ignoreComments) :filter(function(_, conf) return conf.doesNotUseCodes end) :map(function(linter, _) return linter end) :totable() - if vim.tbl_contains(sourcesWithNoCodes, diag.source) then return true end + return not vim.tbl_contains(sourcesWithNoCodes, diag.source) +end + +---checks whether rule has id and source, as prescribed in nvim diagnostic structure +---@param diag vim.Diagnostic +---@return boolean +---@nodiscard +local function validDiagObj(diag) + if not sourceUsesCodes(diag) then return true end local issuePlea = "\nIf you are using efm or nvim-lint, please check your linter config. Otherwise open an issue at the diagnostic source or the diagnostic provider." - if not diag.code then - notify("Diagnostic is missing a code (rule id)." .. issuePlea, "warn") - return false - elseif not diag.source then + if not diag.source then notify("Diagnostic is missing a source." .. issuePlea, "warn") return false + elseif not diag.code and sourceUsesCodes(diag) then + notify("Diagnostic is missing a code (rule id)." .. issuePlea, "warn") + return false end return true end @@ -56,13 +63,17 @@ end ---@param diag vim.Diagnostic function M.ignoreRule(diag) + local configForSource = require("rulebook.config").config.ignoreComments[diag.source] + if not configForSource then + notify(("No ignore comment configured for %q."):format(diag.source), "warn") + return + end if not validDiagObj(diag) then return end - local config = require("rulebook.config").config local indent = vim.api.nvim_get_current_line():match("^%s*") - local ignoreComment = config.ignoreComments[diag.source].comment + local ignoreComment = configForSource.comment if type(ignoreComment) == "function" then ignoreComment = ignoreComment(diag) end - local ignoreLocation = config.ignoreComments[diag.source].location + local ignoreLocation = configForSource.location -- insert the comment if ignoreLocation == "prevLine" then @@ -98,7 +109,6 @@ end ---@param operation "lookupRule"|"ignoreRule"|"yankDiagnosticCode" function M.selectRule(operation) local config = require("rulebook.config").config - local operationIsIgnore = operation == "ignoreRule" local lnum = vim.api.nvim_win_get_cursor(0)[1] - 1 local startLine = lnum local lastLine = vim.api.nvim_buf_line_count(0) @@ -107,24 +117,12 @@ function M.selectRule(operation) -- loop through lines until we find a line with diagnostics while true do diagsAtLine = vim.diagnostic.get(0, { lnum = lnum }) - if operationIsIgnore then - -- INFO for rule search, there is no need to filter the diagnostics, since there - -- is a fallback mechanic - diagsAtLine = vim.tbl_filter( - function(d) return config.ignoreComments[d.source] ~= nil end, - diagsAtLine - ) - end - - -- no diagnostic -> search the next lines - if #diagsAtLine > 0 then break end + if #diagsAtLine > 0 then break end -- no diagnostic -> search the next lines lnum = lnum + 1 -- GUARD if lnum > lastLine or lnum > startLine + config.forwSearchLines then - local msg = ("No supported diagnostics found in the next %s lines."):format( - config.forwSearchLines - ) + local msg = ("No diagnostics found in the next %s lines."):format(config.forwSearchLines) notify(msg, "warn") return end @@ -133,7 +131,7 @@ function M.selectRule(operation) -- remove duplicate rules local uniqueRule = {} for _, diag in ipairs(diagsAtLine) do - uniqueRule[diag.source .. (diag.code or diag.message)] = diag + uniqueRule[(diag.source or "") .. (diag.code or diag.message)] = diag end diagsAtLine = vim.tbl_values(uniqueRule) @@ -145,7 +143,7 @@ function M.selectRule(operation) -- select from multiple diagnostics local title - if operationIsIgnore then title = "Ignore Rule:" end + if operation == "ignoreRule" then title = "Ignore Rule:" end if operation == "lookupRule" then title = "Lookup Rule:" end if operation == "yankDiagnosticCode" then title = "Yank Diagnostic Code:" end @@ -153,17 +151,26 @@ function M.selectRule(operation) prompt = title, kind = "rule_selection", format_item = function(diag) - local source = diag.source and diag.source .. ": " or "" - local desc = diag.code or diag.message - local display = source .. desc - if not (diag.code and diag.source) then display = " " .. display end + local msg = vim.trim((diag.message or ""):sub(1, 50)) + if not diag.source then return ("[ No source] %s %s"):format(diag.code or "", msg) end + + local display = diag.source .. ": " .. (diag.code or msg) + if operation == "ignoreRule" then + local configForSource = require("rulebook.config").config.ignoreComments[diag.source] + if not configForSource then display = "[ No config] " .. display end + if sourceUsesCodes(diag) and not diag.code then + display = "[ No code] " .. display + end + elseif not diag.code then + display = "[ No code] " .. display + end return display end, }, function(diag) if not diag then return end -- user aborted -- move cursor to location where we add the comment - if operationIsIgnore and startLine ~= lnum then + if operation == "ignoreRule" and startLine ~= lnum then vim.api.nvim_win_set_cursor(0, { lnum + 1, 0 }) vim.cmd("normal! ^") end