mirror of https://github.com/ray-x/go.nvim
Add go coverage
parent
7de6a600f2
commit
b96cdefea3
@ -0,0 +1,258 @@
|
||||
local log = require('go.utils').log
|
||||
local coverage = {}
|
||||
local api = vim.api
|
||||
local M = {}
|
||||
local visable = false
|
||||
_GO_NVIM_CFG = _GO_NVIM_CFG
|
||||
local sign_define_cache = {}
|
||||
|
||||
M.sign_map = {covered = 'goCoverageCovered', uncover = 'goCoverageUncover'}
|
||||
|
||||
local ns = 'gocoverage_ns'
|
||||
|
||||
local sign_covered = M.sign_map.covered
|
||||
local sign_uncover = M.sign_map.uncover
|
||||
|
||||
local function sign_get(bufnr, name)
|
||||
if sign_define_cache[bufnr] == nil then
|
||||
sign_define_cache[bufnr] = {}
|
||||
end
|
||||
if not sign_define_cache[bufnr][name] then
|
||||
local s = vim.fn.sign_getdefined(name)
|
||||
if not vim.tbl_isempty(s) then
|
||||
sign_define_cache[bufnr][name] = s
|
||||
end
|
||||
end
|
||||
return sign_define_cache[bufnr][name]
|
||||
end
|
||||
|
||||
-- all windows and buffers
|
||||
local function all_win_bufnr()
|
||||
local winids = {}
|
||||
local bufnrl = {}
|
||||
for i = 1, vim.fn.tabpagenr('$') do
|
||||
for j = 1, vim.fn.tabpagewinnr(i, '$') do
|
||||
local winid = vim.fn.win_getid(j, i)
|
||||
local bufnr = vim.fn.winbufnr(winid)
|
||||
if vim.fn.buflisted(bufnr) then
|
||||
local fn = vim.fn.bufname(bufnr)
|
||||
local ext = string.sub(fn, #fn - 2)
|
||||
if ext == '.go' then
|
||||
table.insert(winids, winid)
|
||||
table.insert(bufnrl, bufnr)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return winids, bufnrl
|
||||
end
|
||||
|
||||
function M.define(bufnr, name, opts, redefine)
|
||||
if sign_define_cache[bufnr] == nil then
|
||||
sign_define_cache[bufnr] = {}
|
||||
end
|
||||
-- log(bufnr, name, opts, redefine)
|
||||
-- print(bufnr, name, opts, redefine)
|
||||
if redefine then
|
||||
sign_define_cache[bufnr][name] = nil
|
||||
vim.fn.sign_undefine(name)
|
||||
vim.fn.sign_define(name, opts)
|
||||
elseif not sign_get(name) then
|
||||
-- log("define sign", name, vim.inspect(opts))
|
||||
vim.fn.sign_define(name, opts)
|
||||
end
|
||||
-- vim.cmd([[sign list]])
|
||||
end
|
||||
|
||||
function M.remove(bufnr, lnum)
|
||||
if bufnr == nil then
|
||||
bufnr = vim.fn.bufnr('$')
|
||||
end
|
||||
vim.fn.sign_unplace(ns, {buffer = bufnr, id = lnum})
|
||||
end
|
||||
|
||||
local function remove_all()
|
||||
local _, bufnrs = all_win_bufnr()
|
||||
for _, bid in pairs(bufnrs) do
|
||||
M.remove(bid)
|
||||
end
|
||||
end
|
||||
|
||||
function M.add(bufnr, signs)
|
||||
local to_place = {}
|
||||
for _, s in pairs(signs or {}) do
|
||||
|
||||
local count = s.cnt
|
||||
local stype = "goCoverageCovered"
|
||||
if count == 0 then
|
||||
stype = "goCoverageUncover"
|
||||
end
|
||||
|
||||
M.define(bufnr, stype, {text = _GO_NVIM_CFG.gocoverage_sign, texthl = stype})
|
||||
for lnum = s.range.start.line, s.range['end'].line + 1 do
|
||||
to_place[#to_place + 1] = {
|
||||
id = lnum,
|
||||
group = ns,
|
||||
name = stype,
|
||||
buffer = bufnr,
|
||||
lnum = lnum,
|
||||
priority = _GO_NVIM_CFG.gocoverage_sign_priority
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
-- log("placing", to_place)
|
||||
vim.fn.sign_placelist(to_place)
|
||||
return to_place -- for testing
|
||||
end
|
||||
|
||||
M.highlight = function()
|
||||
if vim.o.background == 'dark' then
|
||||
vim.cmd([[hi! goCoverageCovered guifg=#107040 ctermbg=28]])
|
||||
vim.cmd([[hi! goCoverageUncover guifg=#A03040 ctermbg=52]])
|
||||
else
|
||||
vim.cmd([[hi! goCoverageCovered guifg=#70f0d0 ctermbg=120]])
|
||||
vim.cmd([[hi! goCoverageUncover guifg=#f040d0 ctermbg=223]])
|
||||
end
|
||||
end
|
||||
|
||||
local function augroup()
|
||||
vim.cmd([[ augroup gopher.vim-coverage ]])
|
||||
vim.cmd([[ au! ]])
|
||||
vim.cmd([[ au ColorScheme * lua require'go.coverage'.highlight() ]])
|
||||
vim.cmd([[ au BufWinLeave *.go lua require'go.coverage'remove() ]])
|
||||
vim.cmd([[ au BufWinEnter *.go lua require'go.coverage'enable_all() ]])
|
||||
vim.cmd([[ augroup end ]])
|
||||
end
|
||||
|
||||
local function enable_all()
|
||||
local _, bufnrs = all_win_bufnr()
|
||||
for _, bufnr in pairs(bufnrs) do
|
||||
-- enable
|
||||
-- local bufnr = vim.fn.winbufnr(id)
|
||||
local fn = vim.fn.bufname(bufnr)
|
||||
|
||||
local filename = vim.fn.fnamemodify(fn, ":t")
|
||||
if coverage[fn] ~= nil then
|
||||
M.add(bufnr, coverage[fn])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
M.toggle = function(show)
|
||||
if (show == nil and visable == true) or show == false then
|
||||
-- hide
|
||||
visable = false
|
||||
remove_all()
|
||||
return
|
||||
end
|
||||
|
||||
visable = true
|
||||
enable_all()
|
||||
-- end
|
||||
|
||||
end
|
||||
|
||||
local function parse_line(line)
|
||||
local m = vim.fn.matchlist(line, [[\v([^:]+):(\d+)\.(\d+),(\d+)\.(\d+) (\d+) (\d+)]])
|
||||
|
||||
if m == nil or #m == 0 then
|
||||
return {}
|
||||
end
|
||||
local path = m[2]
|
||||
local filename = vim.fn.fnamemodify(m[2], ":t")
|
||||
return {
|
||||
file = path,
|
||||
filename = filename,
|
||||
range = {
|
||||
start = {line = tonumber(m[3]), character = tonumber(m[4])},
|
||||
['end'] = {line = tonumber(m[5]), character = tonumber(m[6])}
|
||||
},
|
||||
num = tonumber(m[7]),
|
||||
cnt = tonumber(m[8])
|
||||
}
|
||||
end
|
||||
|
||||
if vim.tbl_isempty(vim.fn.sign_getdefined(sign_covered)) then
|
||||
vim.fn.sign_define(sign_covered,
|
||||
{text = _GO_NVIM_CFG.gocoverage_sign, texthl = "goCoverageCovered"})
|
||||
end
|
||||
|
||||
if vim.tbl_isempty(vim.fn.sign_getdefined(sign_uncover)) then
|
||||
vim.fn.sign_define(sign_uncover,
|
||||
{text = _GO_NVIM_CFG.gocoverage_sign, texthl = "goCoverageUncover"})
|
||||
end
|
||||
|
||||
M.read_cov = function(covfn)
|
||||
local cov = vim.fn.readfile(covfn)
|
||||
-- log(vim.inspect(cov))
|
||||
for _, line in pairs(cov) do
|
||||
local cl = parse_line(line)
|
||||
if cl.file == nil or cl.range == nil then
|
||||
goto continue
|
||||
end
|
||||
-- log("cl", vim.inspect(cl))
|
||||
if coverage[cl.filename] == nil then
|
||||
coverage[cl.filename] = {}
|
||||
end
|
||||
table.insert(coverage[cl.filename], cl)
|
||||
::continue::
|
||||
end
|
||||
|
||||
local _, bufnrs = all_win_bufnr()
|
||||
log("buffers", bufnrs)
|
||||
for _, bid in pairs(bufnrs) do
|
||||
local bufnr = vim.fn.winbufnr(bid)
|
||||
local fn = vim.fn.bufname(bufnr)
|
||||
|
||||
fn = vim.fn.fnamemodify(fn, ":t")
|
||||
|
||||
M.add(bid, coverage[fn])
|
||||
visable = true
|
||||
end
|
||||
return coverage
|
||||
end
|
||||
|
||||
M.run = function(tag)
|
||||
-- local cov = vim.fn.tempname()
|
||||
local cov = vim.fn.expand("%:p:h") .. "/cover.cov"
|
||||
|
||||
local cmd = {'go', 'test', '-coverprofile', cov}
|
||||
if tag ~= nil then
|
||||
table.insert(cmd, tag)
|
||||
end
|
||||
local lines = {""}
|
||||
coverage = {}
|
||||
table.insert(cmd, "./" .. vim.fn.expand('%:.:h'))
|
||||
log("run coverage", cmd)
|
||||
local j = vim.fn.jobstart(cmd, {
|
||||
on_stdout = function(jobid, data, event)
|
||||
log("go coverage " .. vim.inspect(data))
|
||||
vim.list_extend(lines, data)
|
||||
end,
|
||||
on_stderr = function(job_id, data, event)
|
||||
print("go coverage finished with message: " .. vim.inspect(tag) .. "error: "
|
||||
.. vim.inspect(data) .. "job" .. tostring(job_id) .. "ev" .. event)
|
||||
end,
|
||||
on_exit = function(job_id, data, event)
|
||||
if event ~= "exit" then
|
||||
print(job_id, event, vim.inspect(data))
|
||||
end
|
||||
log("test finished")
|
||||
coverage = M.read_cov(cov)
|
||||
|
||||
-- log("coverage", coverage)
|
||||
|
||||
vim.fn.delete(cov)
|
||||
vim.fn.setqflist({}, " ", {
|
||||
title = cmd,
|
||||
lines = lines
|
||||
-- efm = vim.api.nvim_buf_get_option(bufnr, "errorformat")
|
||||
})
|
||||
vim.api.nvim_command("doautocmd QuickFixCmdPost")
|
||||
vim.cmd([[copen]])
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
return M
|
@ -0,0 +1,22 @@
|
||||
package main
|
||||
|
||||
// import "fmt"
|
||||
|
||||
func branch(a, b int) int {
|
||||
if a == 10 {
|
||||
return 10
|
||||
}
|
||||
if b == 10 {
|
||||
return 20
|
||||
}
|
||||
|
||||
if a == 11 {
|
||||
return 11
|
||||
}
|
||||
|
||||
if b == 11 {
|
||||
return 22
|
||||
}
|
||||
|
||||
return a + b
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func Test_branch(t *testing.T) {
|
||||
type args struct {
|
||||
a int
|
||||
b int
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want int
|
||||
}{
|
||||
// TODO: Add test cases.
|
||||
{
|
||||
name: "a10",
|
||||
args: args{a: 10},
|
||||
want: 10,
|
||||
},
|
||||
{
|
||||
name: "b10",
|
||||
args: args{b: 10},
|
||||
want: 20,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := branch(tt.args.a, tt.args.b); got != tt.want {
|
||||
t.Errorf("branch() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
mode: set
|
||||
github.com/go.nvim/branch.go:3.27,4.13 1 1
|
||||
github.com/go.nvim/branch.go:7.2,7.13 1 1
|
||||
github.com/go.nvim/branch.go:11.2,11.13 1 0
|
||||
github.com/go.nvim/branch.go:15.2,15.13 1 0
|
||||
github.com/go.nvim/branch.go:18.2,18.14 1 0
|
||||
github.com/go.nvim/branch.go:4.13,6.3 1 1
|
||||
github.com/go.nvim/branch.go:7.13,9.3 1 1
|
||||
github.com/go.nvim/branch.go:11.13,13.3 1 0
|
||||
github.com/go.nvim/branch.go:15.13,17.3 1 0
|
@ -0,0 +1,3 @@
|
||||
module github.com/go.nvim
|
||||
|
||||
go 1.17
|
@ -0,0 +1,178 @@
|
||||
local eq = assert.are.same
|
||||
local cur_dir = vim.fn.expand("%:p:h")
|
||||
local busted = require("plenary/busted")
|
||||
|
||||
describe("should read coveragefile", function()
|
||||
-- vim.fn.readfile('minimal.vim')
|
||||
-- vim.fn.writefile(vim.fn.readfile('fixtures/fmt/hello.go'), name)
|
||||
status = require("plenary.reload").reload_module("go.nvim")
|
||||
it("should read coverage file", function()
|
||||
--
|
||||
local path = cur_dir .. "/lua/tests/fixtures/coverage/coverage.out" -- %:p:h ? %:p
|
||||
print("test:" .. path)
|
||||
-- go.nvim may not auto loaded
|
||||
vim.cmd([[packadd go.nvim]])
|
||||
require('go').setup({trace = true, log_path = vim.fn.expand("$HOME") .. "/tmp/gonvim.log"})
|
||||
|
||||
local cover = require("go.coverage")
|
||||
local result = cover.read_cov(path)
|
||||
|
||||
-- print(vim.inspect(result))
|
||||
local n = "github.com/go.nvim/branch.go"
|
||||
local range = {['end'] = {character = 13, line = 4}, start = {character = 27, line = 3}}
|
||||
|
||||
eq(result[n][1].file, "github.com/go.nvim/branch.go")
|
||||
eq(result[n][1].range, range)
|
||||
-- eq(result[n][1], "github.com/go.nvim/branch.go")
|
||||
end)
|
||||
it("should generate sign list", function()
|
||||
--
|
||||
local path = cur_dir .. "/lua/tests/fixtures/coverage/coverage.out" -- %:p:h ? %:p
|
||||
print("test:" .. path)
|
||||
-- go.nvim may not auto loaded
|
||||
vim.cmd([[packadd go.nvim]])
|
||||
require('go').setup({
|
||||
trace = true,
|
||||
log_path = vim.fn.expand("$HOME") .. "/tmp/gonvim.log",
|
||||
gocoverage_sign = '|'
|
||||
})
|
||||
|
||||
local cover = require("go.coverage")
|
||||
cover.highlight()
|
||||
|
||||
local coverage = {
|
||||
{
|
||||
cnt = 1,
|
||||
file = "github.com/go.nvim/branch.go",
|
||||
filename = "branch.go",
|
||||
num = 1,
|
||||
range = {['end'] = {character = 13, line = 4}, start = {character = 27, line = 3}}
|
||||
}, {
|
||||
cnt = 1,
|
||||
file = "github.com/go.nvim/branch.go",
|
||||
filename = "branch.go",
|
||||
num = 1,
|
||||
range = {['end'] = {character = 13, line = 7}, start = {character = 2, line = 7}}
|
||||
}
|
||||
}
|
||||
|
||||
local result = cover.add(1, coverage)
|
||||
-- print(vim.inspect(result))
|
||||
local sign = {
|
||||
buffer = 1,
|
||||
group = 'gocoverage_ns',
|
||||
id = 3,
|
||||
lnum = 3,
|
||||
name = 'goCoverageCovered',
|
||||
priority = 5
|
||||
}
|
||||
eq(result[1], sign)
|
||||
-- eq(result[n][1], "github.com/go.nvim/branch.go")
|
||||
end)
|
||||
|
||||
-- it("should run fmt sending from buffer", function()
|
||||
-- local name = vim.fn.tempname() .. ".go"
|
||||
-- print("tmp:" .. name)
|
||||
-- --
|
||||
-- local path = cur_dir .. "/lua/tests/fixtures/fmt/hello.go" -- %:p:h ? %:p
|
||||
-- print("test:" .. path)
|
||||
-- local lines = vim.fn.readfile(path)
|
||||
-- vim.fn.writefile(lines, name)
|
||||
-- local expected = vim.fn.join(vim.fn.readfile(
|
||||
-- cur_dir .. "/lua/tests/fixtures/fmt/hello_golden.go"), "\n")
|
||||
-- local cmd = " silent exe 'e " .. name .. "'"
|
||||
-- vim.cmd(cmd)
|
||||
-- local l = vim.api.nvim_buf_get_lines(0, 0, -1, true)
|
||||
-- print("buf read: " .. vim.inspect(l))
|
||||
--
|
||||
-- vim.bo.filetype = "go"
|
||||
--
|
||||
-- print("exp:" .. vim.inspect(expected))
|
||||
-- print("tmp" .. name)
|
||||
--
|
||||
-- local gofmt = require("go.format")
|
||||
-- gofmt.gofmt(true)
|
||||
-- -- enable the channel response
|
||||
-- vim.wait(100, function()
|
||||
-- end)
|
||||
-- local fmt = vim.fn.join(vim.fn.readfile(name), "\n")
|
||||
-- print("fmt" .. fmt)
|
||||
-- vim.fn.assert_equal(fmt, expected)
|
||||
-- eq(expected, fmt)
|
||||
-- local cmd = "bd! " .. name
|
||||
-- vim.cmd(cmd)
|
||||
-- end)
|
||||
-- it("should run import from file", function()
|
||||
-- local path = cur_dir .. "/lua/tests/fixtures/fmt/goimports.go" -- %:p:h ? %:p
|
||||
-- local expected = vim.fn.join(vim.fn.readfile(cur_dir
|
||||
-- .. "/lua/tests/fixtures/fmt/goimports_golden.go"),
|
||||
-- "\n")
|
||||
-- local name = vim.fn.tempname() .. ".go"
|
||||
-- print(name)
|
||||
-- local lines = vim.fn.readfile(path)
|
||||
-- vim.fn.writefile(lines, name)
|
||||
-- local cmd = " silent exe 'e " .. name .. "'"
|
||||
-- vim.cmd(cmd)
|
||||
--
|
||||
-- vim.cmd([[cd %:p:h]])
|
||||
-- require("go.format").goimport()
|
||||
-- print("workspaces:", vim.inspect(vim.lsp.buf.list_workspace_folders()))
|
||||
-- vim.wait(100, function()
|
||||
-- end)
|
||||
-- local fmt = vim.fn.join(vim.fn.readfile(name), "\n")
|
||||
-- eq(expected, fmt)
|
||||
-- cmd = "bd! " .. name
|
||||
-- vim.cmd(cmd)
|
||||
-- end)
|
||||
-- it("should run import from file with gopls", function()
|
||||
-- local path = cur_dir .. "/lua/tests/fixtures/fmt/goimports2.go" -- %:p:h ? %:p
|
||||
-- local expected = vim.fn.join(vim.fn.readfile(cur_dir
|
||||
-- .. "/lua/tests/fixtures/fmt/goimports2_golden.go"),
|
||||
-- "\n")
|
||||
-- require("go").setup({goimport = "gopls", lsp_cfg = true})
|
||||
--
|
||||
-- _GO_NVIM_CFG.goimport = 'gopls'
|
||||
--
|
||||
-- local lines = vim.fn.readfile(path)
|
||||
-- local cmd = " silent exe 'e " .. path .. "'"
|
||||
-- vim.cmd(cmd)
|
||||
-- vim.wait(1000, function()
|
||||
-- end)
|
||||
--
|
||||
-- vim.cmd([[cd %:p:h]])
|
||||
-- require("go.format").goimport()
|
||||
--
|
||||
-- print("workspaces:", vim.inspect(vim.lsp.buf.list_workspace_folders()))
|
||||
-- vim.wait(200, function()
|
||||
-- end)
|
||||
-- local fmt = vim.fn.join(vim.fn.readfile(path), "\n")
|
||||
-- -- eq(expected, fmt)
|
||||
-- eq(1, 1) -- still not working
|
||||
-- cmd = "bd! " .. path
|
||||
-- vim.cmd(cmd)
|
||||
-- end)
|
||||
-- it("should run import from file buffer with gofumpts", function()
|
||||
-- _GO_NVIM_CFG.goimport = 'gofumports'
|
||||
-- local path = cur_dir .. "/lua/tests/fixtures/fmt/goimports.go" -- %:p:h ? %:p
|
||||
-- local expected = vim.fn.join(vim.fn.readfile(cur_dir
|
||||
-- .. "/lua/tests/fixtures/fmt/goimports_golden.go"),
|
||||
-- "\n")
|
||||
-- local name = vim.fn.tempname() .. ".go"
|
||||
-- print(name)
|
||||
-- local lines = vim.fn.readfile(path)
|
||||
-- local cmd = " silent exe 'e " .. name .. "'"
|
||||
-- vim.fn.writefile(lines, name)
|
||||
-- vim.cmd(cmd)
|
||||
-- vim.cmd([[cd %:p:h]])
|
||||
-- print("code write to " .. name)
|
||||
-- local gofmt = require("go.format")
|
||||
-- gofmt.goimport(true)
|
||||
--
|
||||
-- vim.wait(100, function()
|
||||
-- end)
|
||||
-- local fmt = vim.fn.join(vim.fn.readfile(name), "\n")
|
||||
--
|
||||
-- print(fmt)
|
||||
-- eq(expected, fmt)
|
||||
-- end)
|
||||
end)
|
Loading…
Reference in New Issue