This repository was archived by the owner on Aug 12, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 777
/
Copy pathcredo.lua
111 lines (93 loc) · 3.83 KB
/
credo.lua
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
local h = require("null-ls.helpers")
local methods = require("null-ls.methods")
local DIAGNOSTICS = methods.internal.DIAGNOSTICS
local function generic_issue(message)
return {
message = message,
row = 1,
source = "credo",
}
end
return h.make_builtin({
name = "credo",
meta = {
url = "https://hexdocs.pm/credo",
description = "Static analysis of `elixir` files for enforcing code consistency.",
notes = {
"Searches upwards from the buffer to the project root and tries to find the first `.credo.exs` file in case the project has nested `credo` configs.",
},
},
method = DIAGNOSTICS,
filetypes = { "elixir" },
generator_opts = {
command = "mix",
--NOTE: search upwards to look for the credo config file
cwd = function(params)
local match = vim.fn.findfile(".credo.exs", vim.fn.fnamemodify(params.bufname, ":h") .. ";" .. params.root)
if match then
return vim.fn.fnamemodify(match, ":h")
else
return params.root
end
end,
args = { "credo", "suggest", "--format", "json", "--read-from-stdin", "$FILENAME" },
format = "raw",
to_stdin = true,
on_output = function(params, done)
local issues = {}
-- credo is behaving in a bit of a tricky way:
-- 1. if there are no elixir warnings, it will give its output
-- on stderr, and stdout will be nil
-- 2. if there are elixir warnings, it will report the elixir
-- warnings on stderr, and its own output on stdout
--
-- also note.. "warnings".. this has been reproduced by doing a
-- "mix new" project, then changing in mix.exs "def project" to add:
-- compilers: Mix.compilers(),
-- Then creating a file config/config.exs containing "use Mix.Config"
local output = params.output or params.err
if not output then
return done(issues)
end
local json_index, _ = output:find("{")
-- if no json included, something went wrong and nothing to parse
if not json_index then
table.insert(issues, generic_issue(output))
return done(issues)
end
local maybe_json_string = output:sub(json_index)
local ok, decoded = pcall(vim.json.decode, maybe_json_string)
-- decoding broke, so give up and return the original output
if not ok then
table.insert(issues, generic_issue(output))
return done(issues)
end
for _, issue in ipairs(decoded.issues or {}) do
local err = {
message = issue.message,
row = issue.line_no,
source = "credo",
}
-- using the dynamic priority ranges from credo source
if issue.priority >= 10 then
err.severity = h.diagnostics.severities.error
elseif issue.priority >= 0 then
err.severity = h.diagnostics.severities.warning
elseif issue.priority >= -10 then
err.severity = h.diagnostics.severities.information
else
err.severity = h.diagnostics.severities.hint
end
if issue.column and issue.column ~= vim.NIL then
err.col = issue.column
end
if issue.column_end and issue.column_end ~= vim.NIL then
err.end_col = issue.column_end
end
table.insert(issues, err)
end
done(issues)
end,
},
factory = h.generator_factory,
})