Feature: add go mock / mockgen

pull/163/head
ray-x 2 years ago
parent 2371bf414b
commit a86e9d2a29

@ -18,10 +18,6 @@ jobs:
url: https://github.com/neovim/neovim/releases/download/v0.7.2/nvim-linux64.tar.gz
manager: sudo snap
packages: go
- os: ubuntu-20.04
url: https://github.com/neovim/neovim/releases/download/v0.6.1/nvim-linux64.tar.gz
manager: sudo snap
packages: go
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2

@ -314,8 +314,8 @@ gofmt)
| command | Description |
| --------------------- | --------------------------- |
| GoFmt {opts} | goline + gofumpt |
| GoImport | goline + goimport + gofumpt |
| GoFmt {opts} | default: gofumpt |
| GoImport | default: goimport |
| GoImport package_path | gopls add_import package |
{opts} : ``-a`` format all buffers
@ -378,6 +378,19 @@ Notes:
| GoAltS / GoAltS! | open alternative go file in split |
| GoAltV / GoAltV! | open alternative go file in vertical split |
## Go Mock
go mock with mockgen is supported
| command | Description |
| ---------------- | ------------------------------------------------------- |
| GoMockGen | default: generate mocks for current file |
options:
-s source mode(default)
-i interface mode, provide interface name or put cursor on interface
-p package name default: mocks
-d destination directory, default: ./mocks
## Comments and Doc
Auto doc (to suppress golang-lint warning), generate comments by treesitter parsing result
@ -541,7 +554,7 @@ require('go').setup({
goimport='gopls', -- goimport command, can be gopls[default] or goimport
fillstruct = 'gopls', -- can be nil (use fillstruct, slower) and gopls
gofmt = 'gofumpt', --gofmt cmd,
max_line_len = 120, -- max line length in goline format
max_line_len = 128, -- max line length in golines format, Target maximum line length for golines
tag_transform = false, -- can be transform option("snakecase", "camelcase", etc) check gomodifytags for details and more options
gotests_template = "", -- sets gotests -template parameter (check gotests for details)
gotests_template_dir = "", -- sets gotests -template_dir parameter (check gotests for details)

@ -297,6 +297,14 @@ COMMANDS *go-nvim-commands*
:GoDoc {options} *:GoDoc*
e.g. GoDoc fmt.Println
:GoMockGen {options} *:GoDoc*
Generate mock with go mock
options:
-s source mode(default)
-i interface mode, provide interface name or put cursor on interface
-p package name default: mocks
-d destination directory, default: ./mocks
:GoPkgOutline {options} *:GoPkgOutline*
show symbols inside a specific package in side panel/loclist
options: -f (floating win), -p package_name

@ -1,6 +1,8 @@
-- some of commands extracted from gopher.vim
local go = {}
local vfn = vim.fn
local create_cmd = vim.api.nvim_create_user_command
-- Keep this in sync with README.md
-- Keep this in sync with doc/go.txt
_GO_NVIM_CFG = {
@ -8,7 +10,7 @@ _GO_NVIM_CFG = {
goimport = "gopls", -- if set to 'gopls' will use gopls format, also goimport
fillstruct = "gopls",
gofmt = "gofumpt", -- if set to gopls will use gopls format
max_line_len = 120,
max_line_len = 128,
tag_transform = false,
gotests_template = "", -- sets gotests -template parameter (check gotests for details)
@ -209,6 +211,9 @@ function go.setup(cfg)
vim.cmd([[command! -bang GoCallstack lua require"go.guru".callstack(-1)]])
vim.cmd([[command! -bang GoChannel lua require"go.guru".channel_peers(-1)]])
if _GO_NVIM_CFG.dap_debug then
dap_config()
vim.cmd(
@ -231,6 +236,16 @@ function go.setup(cfg)
vim.cmd([[command! GoDbgStop lua require'go.dap'.stop(true)]])
vim.cmd([[command! GoDbgContinue lua require'dap'.continue()]])
create_cmd('GoMockGen',
require"go.mockgen".run,
{
nargs = "*",
-- bang = true,
complete = function(ArgLead, CmdLine, CursorPos)
-- return completion candidates as a list-like table
return { '-p', '-d', '-i', '-s'}
end,
})
end
require("go.project").load_project()
@ -257,6 +272,9 @@ function go.setup(cfg)
if _GO_NVIM_CFG.textobjects then
require("go.ts.textobjects").setup()
end
require("go.env").setup()
end

@ -48,10 +48,13 @@ local function setup_telescope()
bind.nvim_load_mapping(ts_keys)
end
local keymaps_backup
local function keybind()
if not _GO_NVIM_CFG.dap_debug_keymap then
return
end
-- TODO: put keymaps back
keymaps_backup = vim.api.nvim_get_keymap("n")
keys = {
-- DAP --
-- run

@ -20,7 +20,8 @@ local url = {
dlv = "github.com/go-delve/delve/cmd/dlv",
ginkgo = "github.com/onsi/ginkgo/ginkgo",
richgo = "github.com/kyoh86/richgo",
gotestsum = "gotest.tools/gotestsum"
gotestsum = "gotest.tools/gotestsum",
mockgen = "github.com/golang/mock"
}
local tools = {}

@ -0,0 +1,113 @@
-- local ts_utils = require 'nvim-treesitter.ts_utils'
local utils = require("go.utils")
local log = utils.log
local vfn = vim.fn
local mockgen = "mockgen" -- GoMock f *Foo io.Writer
-- use ts to get name
local function get_interface_name()
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
local name = require("go.ts.go").get_interface_node_at_pos(row, col)
if name == nil then
return nil
end
utils.log(name)
if name == nil then
return ""
end
local node_name = name.name
-- let move the cursor to end of line of struct name
local dim = name.dim.e
-- let move cursor
local r, c = dim.r, dim.c
utils.log("move cusror to ", r, c)
vim.api.nvim_win_set_cursor(0, { r, c })
return node_name
end
local run = function(opts)
require("go.install").install(mockgen)
local long_opts = {
package = "p",
source = "s",
destination = "d",
interface = "i",
}
local getopt = require("go.alt_getopt")
local short_opts = "p:d:i:s"
local args = opts.fargs or {}
log(args)
local optarg, _, reminder = getopt.get_opts(args, short_opts, long_opts)
local mockgen_cmd = { mockgen }
utils.log(arg)
local sep = require("go.utils").sep()
local ifname = get_interface_name()
if optarg["i"] ~= nil and #optarg["i"] > 0 then
ifname = optarg["i"]
end
local fpath = utils.rel_path(true) -- rel/path/only
log(fpath, mockgen_cmd)
local sname = vfn.expand("%:t") -- name.go only
if fpath ~= "" then
fpath = fpath .. sep
end
if ifname == "" then
-- source mode default
table.insert(mockgen_cmd, "-source")
table.insert(mockgen_cmd, fpath .. sname)
else
-- need to get the import path
local bufnr = vim.api.nvim_get_current_buf()
local pkg = require("go.package").pkg_from_path(nil, bufnr)
if pkg ~= nil and type(pkg) == "table" and pkg[1] then
table.insert(mockgen_cmd, pkg[1])
end
table.insert(mockgen_cmd, ifname)
end
local pkgname = optarg["p"] or "mocks"
table.insert(mockgen_cmd, "-package")
table.insert(mockgen_cmd, pkgname)
local dname = fpath .. pkgname .. sep .. "mock_" .. sname
table.insert(mockgen_cmd, "-destination")
table.insert(mockgen_cmd, dname)
log(mockgen_cmd)
utils.log(mockgen_cmd)
-- vim.cmd("normal! $%") -- do a bracket match. changed to treesitter
local opts = {
on_exit = function(code, signal, data)
if code ~= 0 or signal ~= 0 then
-- there will be error popup from runner
-- utils.warn("mockgen failed" .. vim.inspect(data))
return
end
data = vim.split(data, "\n")
data = utils.handle_job_data(data)
if not data then
return
end
--
vim.schedule(function()
utils.info(vfn.join(mockgen_cmd, " ") .. " finished " .. vfn.join(data, " "))
end)
end,
}
local runner = require("go.runner")
runner.run(mockgen_cmd, opts)
return mockgen_cmd
end
return { run = run }

@ -35,11 +35,14 @@ local run = function(cmd, opts)
local output_buf = ""
local function update_chunk_fn(err, chunk)
if err then
return vim.notify("error " .. tostring(err) .. vim.inspect(chunk or {}), vim.lsp.log_levels.INFO)
vim.schedule(function()
vim.notify("error " .. tostring(err) .. vim.inspect(chunk or ""), vim.lsp.log_levels.WARN)
end)
end
if chunk then
output_buf = output_buf .. chunk
end
log(err, chunk)
end
local update_chunk = opts.update_chunk or update_chunk_fn
@ -58,47 +61,43 @@ local run = function(cmd, opts)
handle:close()
log(output_buf)
if code == 0 then
if opts and opts.on_exit then
-- if on_exit hook is on the hook output is what we want to show in loc
-- this avoid show samething in both on_exit and loc
output_buf = opts.on_exit(code, signal, output_buf)
if not output_buf then
return
end
end
if code ~= 0 then
vim.notify(cmd_str .. " failed exit code " .. tostring(code) .. output_buf,
vim.lsp.log_levels.WARN)
if opts and opts.on_exit then
-- if on_exit hook is on the hook output is what we want to show in loc
-- this avoid show samething in both on_exit and loc
output_buf = opts.on_exit(code, signal, output_buf)
if not output_buf then
return
end
if output_buf ~= "" then
local lines = vim.split(output_buf, "\n", true)
lines = util.handle_job_data(lines)
local locopts = {
title = vim.inspect(cmd),
lines = lines,
}
if opts.efm then
locopts.efm = opts.efm
end
log(locopts)
if #lines > 0 then
vim.schedule(function()
vim.fn.setloclist(0, {}, " ", locopts)
vim.cmd("lopen")
end)
end
end
if code ~= 0 then
log("failed to run", code, output_buf)
output_buf = output_buf or ""
vim.notify(cmd_str .. " failed exit code " .. tostring(code) .. output_buf, vim.lsp.log_levels.WARN)
end
if output_buf ~= "" then
local lines = vim.split(output_buf, "\n", true)
lines = util.handle_job_data(lines)
local locopts = {
title = vim.inspect(cmd),
lines = lines,
}
if opts.efm then
locopts.efm = opts.efm
end
log(locopts)
if #lines > 0 then
vim.schedule(function()
vim.fn.setloclist(0, {}, " ", locopts)
vim.cmd("lopen")
end)
end
end
end
)
uv.read_start(stderr, function(err, data)
assert(not err, err)
if data then
vim.notify(string.format("stderr chunk %s %s", stderr, vim.inspect(data)), vim.lsp.log_levels.DEBUG)
end
update_chunk("stderr: " .. tostring(err), data)
end)
stdout:read_start(update_chunk)
-- stderr:read_start(update_chunk)

@ -250,8 +250,7 @@ util.log = function(...)
end
end
util.trace = function(...)
end
util.trace = function(...) end
local rhs_options = {}
@ -443,6 +442,7 @@ function util.info(msg)
end
function util.rel_path(folder)
-- maybe expand('%:p:h:t')
local mod = "%:p"
if folder then
mod = "%:p:h"
@ -451,10 +451,18 @@ function util.rel_path(folder)
local workfolders = vim.lsp.buf.list_workspace_folders()
if workfolders ~= nil and next(workfolders) then
if fn.empty(workfolders) == 0 then
fpath = "." .. fpath:sub(#workfolders[1] + 1)
else
fpath = fn.fnamemodify(fn.expand(mod), ":p:.")
end
util.log(fpath:sub(#fpath), fpath, util.sep())
if fpath:sub(#fpath) == util.sep() then
fpath = fpath:sub(1, #fpath - 1)
util.log(fpath)
end
return "." .. util.sep() .. fn.fnamemodify(fn.expand(mod), ":.")
return fpath
end
function util.trim(s)

@ -2,5 +2,5 @@ package main
func foo() {
fmt.Println("go.nvim")
time.Date(2020, 1, 1, 1, 1, 1, 1, nil)
time.Date(2020, 1, 1, 1, 1, 1, 1, nil)
}

@ -0,0 +1,3 @@
module main
go 1.18

@ -3,46 +3,53 @@
package main
import (
"fmt"
"math"
"fmt"
"math"
"reflect"
)
type Geometry interface {
Area() float64
perim() float64
Area() float64
perim() float64
}
type rect struct {
width, height float64
width, height float64
}
type circle struct {
radius float64
radius float64
}
func (r rect) Area() float64 {
return r.width * r.height
return r.width * r.height
}
func (r rect) perim() float64 {
return 2*r.width + 2*r.height
return 2*r.width + 2*r.height
}
func (c circle) Area() float64 {
return math.Pi * c.radius * c.radius
return math.Pi * c.radius * c.radius
}
func (c circle) perim() float64 {
return 2 * math.Pi * c.radius
return 2 * math.Pi * c.radius
}
func measure(g Geometry) {
fmt.Println(g)
fmt.Println(g.Area())
fmt.Println(g.perim())
fmt.Println(g)
fmt.Println(g.Area())
fmt.Println(g.perim())
}
func main() {
r := rect{width: 3, height: 4}
c := circle{radius: 5}
r := rect{width: 3, height: 4}
c := circle{radius: 5}
var b Geometry = rect{}
fmt.Println(reflect.TypeOf(b).PkgPath())
measure(r)
measure(c)
measure(r)
measure(c)
}

@ -0,0 +1,43 @@
package pkg
import (
"fmt"
"math"
)
type Geometry interface {
area() float64
perim() float64
}
type rect struct {
width float64 `-line:"width"`
height float64 `-line:"height"`
}
func (r rect) area() float64 {
return r.width * r.height
}
func (r rect) perim() float64 {
return 2*r.width + 2*r.height
}
type circle struct {
radius float64
}
func (c circle) area() float64 {
return math.Pi * c.radius * c.radius
}
func (c circle) perim() float64 {
return 2 * math.Pi * c.radius
}
func measure(g Geometry) int {
fmt.Println(g)
fmt.Println(g.area())
fmt.Println(g.perim())
return 1
}

@ -69,7 +69,7 @@ func (p *playlist) NextSong() *song { // exported
return p.nowPlaying
}
func main() {
func play() {
playlistName := "myplaylist"
myPlaylist := createPlaylist(playlistName)
fmt.Println("Created playlist")

@ -0,0 +1,45 @@
local _ = require("plenary/busted")
local fn = vim.fn
local eq = assert.are.same
local cur_dir = vim.fn.expand("%:p:h")
-- local status = require("plenary.reload").reload_module("go.nvim")
-- status = require("plenary.reload").reload_module("nvim-treesitter")
-- local ulog = require('go.utils').log
describe("should run mockgen", function()
vim.cmd([[packadd go.nvim]])
vim.cmd([[packadd nvim-treesitter]])
status = require("plenary.reload").reload_module("go.nvim")
status = require("plenary.reload").reload_module("nvim-treesitter/nvim-treesitter")
require("go").setup({ verbose = true })
it("should run mockgen", function()
--
local path = cur_dir .. "/lua/tests/fixtures/ts/interface.go" -- %:p:h ? %:p
local got = "pkg/mocks/mock_interface.go"
local cmd = " silent exe 'e " .. path .. "'"
vim.cmd(cmd)
vim.cmd("cd lua/tests/fixtures/ts")
local bufn = fn.bufnr("")
vim.fn.setpos(".", { bufn, 10, 11, 0 })
vim.bo.filetype = "go"
local gomockgen = require("go.mockgen")
local cmd = gomockgen.run({ args = { "-s" } })
vim.wait(400, function() end)
local expected_cmd = {
"mockgen",
"-package",
"mocks",
"-source",
"interface.go",
"-destination",
"mocks/mock_interface.go",
}
eq(cmd, expected_cmd)
eq(fn.filereadable(got), 1)
end)
end)
Loading…
Cancel
Save