-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlinting.lua
More file actions
136 lines (123 loc) · 4.13 KB
/
linting.lua
File metadata and controls
136 lines (123 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
return {
"mfussenegger/nvim-lint",
event = "VeryLazy",
opts = {
-- Event to trigger linters
events = { "BufWritePost", "BufReadPost", "InsertLeave" },
linters_by_ft = {
python = { "mypy" },
-- markdown = { "markdownlint-cli2" },
yaml = { "github_action_lint" },
sql = { "sqlfluff" },
mysql = { "sqruff" },
},
linters = {
github_action_lint = {
cmd = "actionlint",
stdin = true,
args = { "-format", "{{json .}}", "-" },
ignore_exitcode = true,
parser = function(output, bufnr, _)
local filepath = vim.api.nvim_buf_get_name(bufnr)
-- Check if the file is under .github/workflows
if not filepath:match "%.github/workflows/.*%.y[a]?ml$" then
return {}
end
if output == "" then
return {}
end
local decoded = vim.json.decode(output)
if decoded == nil then
return {}
end
local diagnostics = {}
for _, item in ipairs(decoded) do
table.insert(diagnostics, {
bufnr = bufnr,
lnum = item.line - 1,
end_lnum = item.line - 1,
col = item.column - 1,
end_col = item.end_column,
severity = vim.diagnostic.severity.WARN,
source = "actionlint: " .. item.kind,
message = item.message,
})
end
return diagnostics
end,
},
},
},
config = function(_, opts)
local M = {}
local lint = require "lint"
for name, linter in pairs(opts.linters) do
if type(linter) == "table" and type(lint.linters[name]) == "table" then
lint.linters[name] =
---@diagnostic disable-next-line: param-type-mismatch
vim.tbl_deep_extend("force", lint.linters[name], linter)
if type(linter.prepend_args) == "table" then
lint.linters[name].args = lint.linters[name].args or {}
vim.list_extend(lint.linters[name].args, linter.prepend_args)
end
else
lint.linters[name] = linter
end
end
lint.linters_by_ft = opts.linters_by_ft
function M.debounce(ms, fn)
local timer = assert(vim.uv.new_timer())
return function(...)
local argv = { ... }
timer:start(ms, 0, function()
timer:stop()
vim.schedule_wrap(fn)(unpack(argv))
end)
end
end
function M.lint()
-- Use nvim-lint's logic first:
-- * checks if linters exist for the full filetype first
-- * otherwise will split filetype by "." and add all those linters
-- * this differs from conform.nvim which only uses the first filetype that has a formatter
local names = lint._resolve_linter_by_ft(vim.bo.filetype)
-- Create a copy of the names table to avoid modifying the original.
names = vim.list_extend({}, names)
-- Add fallback linters.
if #names == 0 then
vim.list_extend(names, lint.linters_by_ft["_"] or {})
end
-- Add global linters.
vim.list_extend(names, lint.linters_by_ft["*"] or {})
-- Filter out linters that don't exist or don't match the condition.
local ctx = { filename = vim.api.nvim_buf_get_name(0) }
ctx.dirname = vim.fn.fnamemodify(ctx.filename, ":h")
names = vim.tbl_filter(function(name)
local linter = lint.linters[name]
if not linter then
vim.notify(
"Linter not found: " .. name,
vim.log.levels.WARN,
{ title = "nvim-lint" }
)
end
return linter
and not (
type(linter) == "table"
---@diagnostic disable-next-line: undefined-field
and linter.condition
---@diagnostic disable-next-line: undefined-field
and not linter.condition(ctx)
)
end, names)
-- Run linters.
if #names > 0 then
lint.try_lint(names)
end
end
vim.api.nvim_create_autocmd(opts.events, {
group = vim.api.nvim_create_augroup("nvim-lint", { clear = true }),
callback = M.debounce(100, M.lint),
})
end,
}