Skip to content

Commit edf6c86

Browse files
authored
refactor: convert checkmake and prettierd from fn to standard config (#81)
* test: add tests for all remaining tools Problem: most formatters and linters in guard-collection had no test coverage. The csharpier binary was renamed in v1.0+ and ruff's -e flag was deprecated in favor of the check subcommand. Solution: add 42 test files covering every remaining tool, fix the csharpier and ruff definitions, extend the install script with gz/jar archive types, add 6 new CI jobs (dotnet, ruby, clojure, elixir, nix, swift), and expand existing jobs with newly tested tools. * fix(ci): remove duplicate entry and untestable mypyc test * fix(ci): restore CI config lost during merge Problem: the -X theirs merge strategy replaced the full test/all-tools CI config with the smaller fix/broken-configs version, losing install entries for dart, fish_indent, google-java-format, pg_format, tombi, typos, typstyle, xmllint, and zigfmt. Solution: restore binary.txt, ci.yaml, and install script from the pre-merge test/all-tools state which already had all entries. * ci: extract repeated test setup into composite action Problem: every test job repeated the same 5 steps for neovim, lua, luarocks, busted/nlua, and guard.nvim clone — 175 lines of duplication across 15 jobs. Solution: extract into .github/actions/test-setup/action.yml and replace with a single `uses: ./.github/actions/test-setup` per job. * fix(test): use run_lint/run_fmt instead of manual vim.system Problem: rebase picked up old test versions that manually construct commands instead of using the config-driven helpers, defeating the purpose of testing the actual tool definitions. Solution: replace all 14 affected test files with the upstream/main versions that use run_lint/run_fmt. Add buf lint test using run_lint. * refactor: convert checkmake and prettierd from fn to standard config Problem: checkmake and prettierd used custom fn handlers to spawn processes manually, duplicating what guard.nvim's standard cmd/args/parse pipeline already does. This prevented their tests from using the shared run_lint/run_fmt helpers. Solution: replace fn with cmd/args/fname fields. Update tests to use run_lint and run_fmt instead of manual vim.system calls. * ci(cljfmt): use standalone binary and extract apt packages to file Problem: cljfmt required a dedicated CI job with Java, Clojure CLI, a hand-rolled wrapper script, and dep pre-warming. The binary job also had an inline apt-get install command inconsistent with other tool lists. Solution: switch cljfmt to the standalone GraalVM binary from GitHub releases, move its test into test/binary/, delete the test-clojure job, and extract the binary job's apt packages into binary-apt.txt. * test: exercise fn-based linter configs via coroutine helper Problem: cpplint and zsh tests bypassed the fn config entirely by manually constructing vim.system calls, so drift between the test and the actual config could go undetected. Solution: add run_lint_fn helper that wraps the fn call in a coroutine and pumps the event loop via vim.wait, then update cpplint and zsh tests to use it. * refactor(test): run assertions inside coroutine in run_lint_fn Problem: run_lint_fn busy-waited on an intermediate output variable, then ran parse and returned results outside the coroutine. Solution: accept an assertion callback, run the full pipeline (fn, parse, assertions) inside the coroutine, and poll only on a completion flag.
1 parent ea1d770 commit edf6c86

7 files changed

Lines changed: 53 additions & 91 deletions

File tree

lua/guard-collection/formatter.lua

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -186,29 +186,9 @@ M.prettier = {
186186
}
187187

188188
M.prettierd = {
189-
fn = function(buf, range)
190-
if vim.fn.has('nvim-0.10') ~= 1 then
191-
vim.notify('[guard-collection]: prettierd uses vim.system introduced in nvim 0.10', 4)
192-
return
193-
end
194-
local srow = range and range['start'][1] or 0
195-
local erow = range and range['end'][1] or -1
196-
local handle = vim.system(
197-
{ 'prettierd', vim.api.nvim_buf_get_name(buf) },
198-
{
199-
stdin = true,
200-
},
201-
vim.schedule_wrap(function(result)
202-
if result.code ~= 0 then
203-
return
204-
end
205-
vim.api.nvim_buf_set_lines(buf, srow, erow, false, vim.split(result.stdout, '\r?\n'))
206-
vim.cmd('silent! noautocmd write!')
207-
end)
208-
)
209-
handle:write(table.concat(vim.api.nvim_buf_get_lines(buf, srow, erow, false), '\n'))
210-
handle:write(nil)
211-
end,
189+
cmd = 'prettierd',
190+
stdin = true,
191+
fname = true,
212192
}
213193

214194
M.rubocop = {

lua/guard-collection/linter/checkmake.lua

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,9 @@
11
local lint = require('guard.lint')
22

33
return {
4-
fn = function(_, fname)
5-
local co = assert(coroutine.running())
6-
vim.system({
7-
'checkmake',
8-
'--format={{.FileName}}:{{.LineNumber}}: [{{.Rule}}] {{.Violation}}\n',
9-
fname,
10-
}, {}, function(result)
11-
coroutine.resume(co, result.stdout or '')
12-
end)
13-
return coroutine.yield()
14-
end,
4+
cmd = 'checkmake',
5+
args = { '--format={{.FileName}}:{{.LineNumber}}: [{{.Rule}}] {{.Violation}}\n' },
6+
fname = true,
157
parse = function(result, bufnr)
168
local diags = {}
179
for line in result:gmatch('[^\n]+') do

test/binary/checkmake_spec.lua

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,13 @@
11
describe('checkmake', function()
22
it('can lint', function()
3-
local linter = require('test.helper').get_linter('checkmake')
4-
local tmpfile = '/tmp/guard-test.make'
5-
local input = {
3+
local helper = require('test.helper')
4+
local buf, diagnostics = helper.run_lint('checkmake', 'make', {
65
[[all:]],
76
[[\techo hello]],
8-
}
9-
vim.fn.writefile(input, tmpfile)
10-
local bufnr = vim.api.nvim_create_buf(false, true)
11-
local result = vim
12-
.system({
13-
'checkmake',
14-
'--format={{.FileName}}:{{.LineNumber}}: [{{.Rule}}] {{.Violation}}\n',
15-
tmpfile,
16-
}, {})
17-
:wait()
18-
local output = result.stdout or ''
19-
local diagnostics = linter.parse(output, bufnr)
7+
})
208
assert.is_true(#diagnostics > 0)
219
for _, d in ipairs(diagnostics) do
22-
assert.equal(bufnr, d.bufnr)
10+
assert.equal(buf, d.bufnr)
2311
assert.equal('checkmake', d.source)
2412
assert.is_number(d.lnum)
2513
assert.is_string(d.message)

test/binary/zsh_spec.lua

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,13 @@
11
describe('zsh', function()
22
it('can lint', function()
3-
local linter = require('test.helper').get_linter('zsh')
4-
local tmpfile = '/tmp/guard-test.zsh'
5-
vim.fn.writefile({ 'if true; then' }, tmpfile)
6-
local bufnr = vim.api.nvim_create_buf(false, true)
7-
local result = vim.system({ 'zsh', '-n', tmpfile }, {}):wait()
8-
local output = result.stderr or ''
9-
local diagnostics = linter.parse(output, bufnr)
10-
assert.is_true(#diagnostics > 0)
11-
for _, d in ipairs(diagnostics) do
12-
assert.equal(bufnr, d.bufnr)
13-
assert.equal('zsh', d.source)
14-
assert.is_number(d.lnum)
15-
assert.is_string(d.message)
16-
end
3+
local helper = require('test.helper')
4+
helper.run_lint_fn('zsh', 'zsh', { 'if true; then' }, function(bufnr, diagnostics)
5+
assert.is_true(#diagnostics > 0)
6+
for _, d in ipairs(diagnostics) do
7+
helper.assert_diag(d, { bufnr = bufnr, source = 'zsh' })
8+
assert.is_number(d.lnum)
9+
assert.is_string(d.message)
10+
end
11+
end)
1712
end)
1813
end)

test/helper.lua

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,27 @@ function M.run_lint(name, ft, input, opts)
5555
return bufnr, diags
5656
end
5757

58+
function M.run_lint_fn(name, ft, input, assert_fn)
59+
local linter = require('guard-collection.linter')[name]
60+
assert(linter, 'unknown linter: ' .. name)
61+
assert(linter.fn, name .. ' does not use custom fn')
62+
local tmpfile = '/tmp/guard-test.' .. ft
63+
vim.fn.writefile(input, tmpfile)
64+
local bufnr = api.nvim_create_buf(false, true)
65+
local done = false
66+
local co = coroutine.create(function()
67+
local output = linter.fn(nil, tmpfile)
68+
local diags = linter.parse(output, bufnr)
69+
assert_fn(bufnr, diags)
70+
done = true
71+
end)
72+
coroutine.resume(co)
73+
vim.wait(5000, function()
74+
return done
75+
end)
76+
assert(done, name .. ' fn timed out')
77+
end
78+
5879
function M.assert_diag(d, expect)
5980
local a = require('luassert')
6081
if expect.bufnr then

test/npm/prettierd_spec.lua

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,12 @@
11
describe('prettierd', function()
22
it('can format', function()
3-
local tmpfile = '/tmp/guard-test.js'
4-
local input = {
3+
local formatted = require('test.helper').run_fmt('prettierd', 'js', {
54
'const x={a:1,b:2,c:3}',
65
'const y = [1,2,3,4,5]',
7-
}
8-
vim.fn.writefile(input, tmpfile)
9-
local result = vim
10-
.system({ 'prettierd', tmpfile }, { stdin = table.concat(input, '\n') })
11-
:wait()
12-
assert.equal(0, result.code)
13-
local expected = table.concat({
6+
})
7+
assert.are.same({
148
'const x = { a: 1, b: 2, c: 3 };',
159
'const y = [1, 2, 3, 4, 5];',
16-
'',
17-
}, '\n')
18-
assert.equal(expected, result.stdout)
10+
}, formatted)
1911
end)
2012
end)

test/pip/cpplint_spec.lua

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
11
describe('cpplint', function()
22
it('can lint', function()
3-
local linter = require('test.helper').get_linter('cpplint')
4-
local tmpfile = '/tmp/guard-test.cpp'
5-
local input = { [[int main(){int x=1;}]] }
6-
vim.fn.writefile(input, tmpfile)
7-
local bufnr = vim.api.nvim_create_buf(false, true)
8-
local result = vim.system({ 'cpplint', '--filter=-legal/copyright', tmpfile }, {}):wait()
9-
local output = result.stderr or ''
10-
local diagnostics = linter.parse(output, bufnr)
11-
assert.is_true(#diagnostics > 0)
12-
for _, d in ipairs(diagnostics) do
13-
assert.equal(bufnr, d.bufnr)
14-
assert.equal('cpplint', d.source)
15-
assert.is_number(d.lnum)
16-
assert.is_string(d.message)
17-
end
3+
local helper = require('test.helper')
4+
helper.run_lint_fn('cpplint', 'cpp', { [[int main(){int x=1;}]] }, function(bufnr, diagnostics)
5+
assert.is_true(#diagnostics > 0)
6+
for _, d in ipairs(diagnostics) do
7+
helper.assert_diag(d, { bufnr = bufnr, source = 'cpplint' })
8+
assert.is_number(d.lnum)
9+
assert.is_string(d.message)
10+
end
11+
end)
1812
end)
1913
end)

0 commit comments

Comments
 (0)