Skip to content

Commit

Permalink
feat(ignoreRule): support comments disabling multiple rules (#2)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisgrieser committed Nov 17, 2024
1 parent ceb5fbd commit 8beb196
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 3 deletions.
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,12 +152,23 @@ require("rulebook").setup = ({
shellcheck = {
comment = "# shellcheck disable=%s",
location = "prevLine",
multiRuleIgnore = true,
multiRuleSeparator = ",",
},
-- ... (full list of sources with builtin support can be found in the README)

yourCustomSource = { -- exact, case-sensitive source-name
comment = "// disabling-comment %s", -- `%s` will be replaced with rule-id
location = "prevLine", -- "prevLine"|"sameLine"|"encloseLine"
-- `%s` will be replaced with rule-id
comment = "// disabling-comment %s",

---@type "prevLine"|"sameLine"|"encloseLine"
location = "sameLine",

--if whether multiple rules can be ignored with one comment, defaults to `false`
multiRuleIgnore = true,

-- separator for multiple rule-ids, defaults to ", "
multiRuleSeparator = ",",
}

-- if location is "encloseLine", needs to be a list of two strings
Expand Down
3 changes: 3 additions & 0 deletions lua/rulebook/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ local function validateIgnoreComment(config, commentKeyName)
elseif location ~= "encloseLine" and comType ~= "string" and comType ~= "function" then
errorMsg = ("`%s` requires `%s` to be a string or function"):format(location, commentKeyName)
end
if location == "encloseLine" and config.multiRuleIgnore then
errorMsg = "`encloseLine` does not support `multiRuleIgnore`."
end
return errorMsg
end

Expand Down
15 changes: 14 additions & 1 deletion lua/rulebook/data/add-ignore-rule-comment.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
---@field location "prevLine"|"sameLine"|"encloseLine" "encloseLine" is a list with two strings, one to be inserted before and one after
---@field docs string used for auto-generated docs
---@field doesNotUseCodes? boolean the linter does not use codes/rule-ids
---@field multiRuleIgnore? boolean supports multiple rule ignores, assuming codes are separated by commas
---@field multiRuleSeparator? string defaults to ", "

---INFO the key must be named like the exact, case-sensitive `diagnostic.source`
--------------------------------------------------------------------------------
Expand All @@ -13,16 +15,20 @@ M = {
comment = "# shellcheck disable=%s",
location = "prevLine",
docs = "https://www.shellcheck.net/wiki/Ignore",
multiRuleIgnore = true,
multiRuleSeparator = ",", -- with space throws this parsing error: https://www.shellcheck.net/wiki/SC1073
},
selene = {
comment = "-- selene: allow(%s)",
location = "prevLine",
docs = "https://kampfkarren.github.io/selene/usage/filtering.html#allowingdenying-lints-for-an-entire-file",
multiRuleIgnore = true,
},
["Lua Diagnostics."] = { -- Lua LSP
comment = "---@diagnostic disable-line: %s",
location = "sameLine", -- prevLine already available via code action
docs = "https://luals.github.io/wiki/annotations/#diagnostic",
multiRuleIgnore = true,
},
yamllint = {
comment = "# yamllint disable-line rule:%s",
Expand All @@ -33,6 +39,7 @@ M = {
comment = "/* stylelint-disable-next-line %s */",
location = "prevLine",
docs = "https://stylelint.io/user-guide/ignore-code/",
multiRuleIgnore = true,
},
LTeX = {
comment = { "<!-- LTeX: enabled=false -->", "<!-- LTeX: enabled=true -->" },
Expand All @@ -48,21 +55,25 @@ M = {
comment = "# pylint: disable=%s",
location = "sameLine",
docs = "https://pylint.readthedocs.io/en/latest/user_guide/messages/message_control.html",
multiRuleIgnore = true,
},
Pyright = {
comment = "# pyright: ignore [%s]",
location = "sameLine",
docs = "https://microsoft.github.io/pyright/#/comments",
multiRuleIgnore = true,
},
Ruff = {
comment = "# noqa: %s",
location = "sameLine",
docs = "https://docs.astral.sh/ruff/linter/#error-suppression",
multiRuleIgnore = true,
},
eslint = {
comment = "// eslint-disable-next-line %s",
location = "prevLine",
docs = "https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1",
multiRuleIgnore = true,
},
biome = {
-- biome works for css and js, so the comment syntax is dependent on the filetype
Expand All @@ -71,7 +82,8 @@ M = {
return vim.bo.commentstring:format(ignoreText)
end,
location = "prevLine",
docs = "https://biomejs.dev/linter/#ignoring-code",
docs = "https://biomejs.dev/linter/#ignore-code",
multiRuleIgnore = false, -- apparently not supported
},
typescript = {
comment = "// @ts-expect-error", -- https://typescript-eslint.io/rules/prefer-ts-expect-error/
Expand All @@ -95,6 +107,7 @@ M = {
comment = "// NOLINT(%s)",
location = "sameLine",
docs = "https://clang.llvm.org/extra/clang-tidy/#suppressing-undesired-diagnostics",
multiRuleIgnore = true,
},
alex = {
comment = "<!-- alex ignore %s -->",
Expand Down
26 changes: 26 additions & 0 deletions lua/rulebook/diagnostic-actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,42 @@ function actions.ignoreRule(diag)
local ignoreComment = sourceConf.comment
if type(ignoreComment) == "function" then ignoreComment = ignoreComment(diag) end

-- used with `str.match`, this pattern will return the already ignored code(s)
local existingRulePattern = vim.pesc(ignoreComment[1] or ignoreComment)
:gsub("%%%%s", "([%%w,-_]+)") .. "%s*$"

-----------------------------------------------------------------------------
if sourceConf.location == "prevLine" then
---@cast ignoreComment string

if sourceConf.multiRuleIgnore then
local prevLine = vim.api.nvim_buf_get_lines(0, prevLn - 1, prevLn, false)[1]
local oldCode = prevLine:match(existingRulePattern)
if oldCode then
local sep = sourceConf.multiRuleSeparator or ", "
diag.code = oldCode .. sep .. diag.code
vim.api.nvim_buf_set_lines(0, prevLn - 1, prevLn, false, {}) -- = deletes previous line
prevLn = prevLn - 1 -- account for the deleted line
end
end

local comment = indent .. ignoreComment:format(diag.code)
vim.api.nvim_buf_set_lines(0, prevLn, prevLn, false, { comment })
-----------------------------------------------------------------------------
elseif sourceConf.location == "sameLine" then
---@cast ignoreComment string
local curLine = vim.api.nvim_get_current_line():gsub("%s+$", "")

if sourceConf.multiRuleIgnore then
local oldCode = curLine:match(existingRulePattern)
if oldCode then
diag.code = oldCode .. ", " .. diag.code
curLine = curLine
:gsub(existingRulePattern, "") -- remove old ignore comment
:gsub("%s+$", "")
end
end

local comment = ignoreComment:format(diag.code)
local extraSpace = vim.bo.filetype == "python" and " " or "" -- formatters expect an extra space
vim.api.nvim_set_current_line(curLine .. " " .. extraSpace .. comment)
Expand Down

0 comments on commit 8beb196

Please sign in to comment.