[Feature] integrate with null-ls. Add go.nvim as a null-ls source
Run `go test` on file save and show diagnostic messages in LSP virtual text.
This commit is contained in:
parent
793b0d1ede
commit
276ebe8654
27
README.md
27
README.md
@ -946,6 +946,33 @@ end
|
||||
|
||||
|
||||
```
|
||||
## Integrate null-ls
|
||||
### The plugin provides `gotest` LSP diagnostic source for null-ls
|
||||
|
||||
Gotest allow you run `go test <package>` when you save your go file and add diagnostics to nvim
|
||||
|
||||
```lua
|
||||
local null_ls = require("null-ls")
|
||||
local sources = {
|
||||
null_ls.builtins.diagnostics.golangci_lint,
|
||||
null_ls.builtins.diagnostics.revive,
|
||||
null_ls.builtins.formatting.golines.with({
|
||||
extra_args = {
|
||||
"--max-len=180",
|
||||
"--base-formatter=gofumpt",
|
||||
},
|
||||
})
|
||||
}
|
||||
-- for go.nvim
|
||||
local gotest = require("go.null_ls").gotest()
|
||||
table.insert(sources, gotest)
|
||||
null_ls.setup({ sources = sources, debounce = 1000, default_timeout = 5000 })
|
||||
|
||||
-- alternatively
|
||||
null_ls.register(gotest)
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Sample vimrc
|
||||
|
||||
|
@ -88,7 +88,7 @@ M.get_build_tags = function(args, tbl)
|
||||
return
|
||||
end
|
||||
|
||||
local function get_test_path()
|
||||
function M.get_test_path()
|
||||
local path = vim.fn.expand('%:p:h')
|
||||
local relative_path = vim.fn.fnamemodify(path, ':.')
|
||||
if path == relative_path then
|
||||
@ -303,7 +303,7 @@ end
|
||||
M.test_package = function(...)
|
||||
local args = { ... }
|
||||
log(args)
|
||||
local fpath = get_test_path() .. sep .. '...'
|
||||
local fpath = M.get_test_path() .. sep .. '...'
|
||||
utils.log('fpath: ' .. fpath)
|
||||
return run_test(fpath, args)
|
||||
end
|
||||
@ -409,7 +409,7 @@ local function run_tests_with_ts_node(args, func_node, tblcase_ns)
|
||||
table.insert(cmd, [['^]] .. func_node.name .. [[$']] .. tbl_name)
|
||||
end
|
||||
|
||||
local fpath = get_test_path()
|
||||
local fpath = M.get_test_path()
|
||||
table.insert(cmd, fpath)
|
||||
|
||||
if optarg['a'] then
|
||||
|
113
lua/go/null_ls.lua
Normal file
113
lua/go/null_ls.lua
Normal file
@ -0,0 +1,113 @@
|
||||
local vim, fn = vim, vim.fn
|
||||
local utils = require('go.utils')
|
||||
local log = utils.log
|
||||
|
||||
local function handler()
|
||||
local severities = { error = 1, warning = 2, information = 3, hint = 4 }
|
||||
return function(msg, done)
|
||||
if msg == nil or msg.output == nil then
|
||||
return
|
||||
end
|
||||
|
||||
local msgs = msg.output
|
||||
msgs = vim.split(msgs, '\n', true)
|
||||
|
||||
local diags = {}
|
||||
local package, filename, line
|
||||
-- the output is jsonencoded
|
||||
local output = ''
|
||||
|
||||
for _, m in pairs(msgs) do
|
||||
if vim.fn.empty(m) == 0 then
|
||||
local entry = vim.fn.json_decode(m)
|
||||
if entry.Action == 'run' then
|
||||
package = entry.Package
|
||||
output = ''
|
||||
elseif entry.Action == 'output' then
|
||||
log(entry)
|
||||
if vim.fn.empty(entry.Output) == 0 then
|
||||
local ma = vim.fn.matchlist(entry.Output, [[\v\s*(\w+.+\.go):(\d+):]])
|
||||
if ma[2] then
|
||||
log(ma)
|
||||
filename = package .. utils.sep() .. ma[2]
|
||||
if fn.filereadable(filename) == 0 then
|
||||
filename = fn.fnamemodify(fn.expand('%:h'), ':~:.') .. utils.sep() .. ma[2]
|
||||
end
|
||||
line = ma[3]
|
||||
end
|
||||
output = output .. (entry.Output or '')
|
||||
-- log(output or 'nil')
|
||||
end
|
||||
elseif entry.Action == 'pass' or entry.Action == 'skip' then
|
||||
-- log(entry)
|
||||
-- reset
|
||||
output = ''
|
||||
elseif entry.Action == 'fail' and vim.fn.empty(output) == 0 then
|
||||
log(entry)
|
||||
if filename:find(fn.expand('%:t')) then -- can be output from other files
|
||||
table.insert(diags, {
|
||||
file = filename,
|
||||
row = tonumber(line),
|
||||
col = 1,
|
||||
message = output,
|
||||
severity = severities.error,
|
||||
source = 'go test',
|
||||
})
|
||||
end
|
||||
output = ''
|
||||
end
|
||||
end
|
||||
end
|
||||
log(diags)
|
||||
-- local ok, d = pcall(vim.fn.json_decode, msg)
|
||||
return done(diags)
|
||||
end
|
||||
end
|
||||
|
||||
-- register with
|
||||
-- null_ls.register(gotest)
|
||||
return {
|
||||
gotest = function()
|
||||
local nulls = utils.load_plugin('null-ls', 'null-ls')
|
||||
if nulls == nil then
|
||||
vim.notify('failed to load null-ls', vim.lsp.log_levels.WARN)
|
||||
return
|
||||
end
|
||||
|
||||
local null_ls = require('null-ls')
|
||||
local methods = require('null-ls.methods')
|
||||
local DIAGNOSTICS_ON_SAVE = methods.internal.DIAGNOSTICS_ON_SAVE
|
||||
|
||||
return {
|
||||
method = null_ls.methods.DIAGNOSTICS,
|
||||
filetypes = { 'go' },
|
||||
generator = null_ls.generator({
|
||||
command = 'go',
|
||||
args = function()
|
||||
local a = { 'test', '-json' }
|
||||
local pkg = require('go.gotest').get_test_path()
|
||||
table.insert(a, pkg)
|
||||
log(a)
|
||||
return a
|
||||
end,
|
||||
to_stdin = false,
|
||||
method = DIAGNOSTICS_ON_SAVE,
|
||||
from_stderr = false,
|
||||
-- choose an output format (raw, json, or line)
|
||||
-- format = 'json',
|
||||
format = 'raw',
|
||||
check_exit_code = function(code, stderr)
|
||||
local success = code <= 1
|
||||
log(code, stderr)
|
||||
if not success then
|
||||
-- can be noisy for things that run often (e.g. diagnostics), but can
|
||||
-- be useful for things that run on demand (e.g. formatting)
|
||||
vim.notify('go test failed: ' .. tostring(stderr))
|
||||
end
|
||||
return success
|
||||
end,
|
||||
on_output = handler(),
|
||||
}),
|
||||
}
|
||||
end,
|
||||
}
|
Loading…
Reference in New Issue
Block a user