[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
|
## Sample vimrc
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ M.get_build_tags = function(args, tbl)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_test_path()
|
function M.get_test_path()
|
||||||
local path = vim.fn.expand('%:p:h')
|
local path = vim.fn.expand('%:p:h')
|
||||||
local relative_path = vim.fn.fnamemodify(path, ':.')
|
local relative_path = vim.fn.fnamemodify(path, ':.')
|
||||||
if path == relative_path then
|
if path == relative_path then
|
||||||
@ -303,7 +303,7 @@ end
|
|||||||
M.test_package = function(...)
|
M.test_package = function(...)
|
||||||
local args = { ... }
|
local args = { ... }
|
||||||
log(args)
|
log(args)
|
||||||
local fpath = get_test_path() .. sep .. '...'
|
local fpath = M.get_test_path() .. sep .. '...'
|
||||||
utils.log('fpath: ' .. fpath)
|
utils.log('fpath: ' .. fpath)
|
||||||
return run_test(fpath, args)
|
return run_test(fpath, args)
|
||||||
end
|
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)
|
table.insert(cmd, [['^]] .. func_node.name .. [[$']] .. tbl_name)
|
||||||
end
|
end
|
||||||
|
|
||||||
local fpath = get_test_path()
|
local fpath = M.get_test_path()
|
||||||
table.insert(cmd, fpath)
|
table.insert(cmd, fpath)
|
||||||
|
|
||||||
if optarg['a'] then
|
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