quick gen return #170

pull/209/head
ray-x 2 years ago
parent 4f01936c00
commit 28bcaa1f44

@ -529,6 +529,32 @@ Visual select the json and run `GoJson2Struct youStructName`
-bang will put result to register `a`
if ["x] specified, will put get json from clipboard
### Generate return value
* GoGenReturn
create return value for current function
e.g. if we have
```go
func Foo() (int, error) {
return 1, nil
}
```
and in your code you cursor on Foo
```go
Foo()
```
will generate
```go
i, err := Foo()
if err != nil {
return
}
```
### Commands

@ -330,6 +330,9 @@ COMMANDS *go-nvim-commands*
Convert json (visual select) to go struct.
bang: put result to register
\"x : get json from register x
:GoGenReturn
generate return values for current function
==============================================================================
OPTIONS *go-nvim-options*

@ -326,6 +326,11 @@ return {
create_cmd('GoEnv', function(opts)
require('go.env').load_env(unpack(opts.fargs))
end, { nargs = '*' })
create_cmd('GoGenReturn', function()
require('go.lsp').hover_returns()
end)
create_cmd('GoJson2Struct', function(opts) require('go.json2struct').run(opts) end, {
nargs = '*',
bang = true,

@ -1,4 +1,4 @@
local utils = require("go.utils")
local utils = require('go.utils')
local log = utils.log
local vfn = vim.fn
@ -8,40 +8,40 @@ local cmds = {}
-- "executeCommandProvider":{"commands":["gopls.add_dependency","gopls.add_import","gopls.apply_fix","gopls.check_upgrades","gopls.gc_details","gopls.generate","gopls.generate_gopls_mod","gopls.go_get_package","gopls.list_known_packages","gopls.regenerate_cgo","gopls.remove_dependency","gopls.run_tests","gopls.start_debugging","gopls.test","gopls.tidy","gopls.toggle_gc_details","gopls.update_go_sum","gopls.upgrade_dependency","gopls.vendor","gopls.workspace_metadata"]}
local gopls_cmds = {
"gopls.add_dependency",
"gopls.add_import",
"gopls.apply_fix",
"gopls.check_upgrades",
"gopls.gc_details",
"gopls.generate",
"gopls.generate_gopls_mod",
"gopls.go_get_package",
"gopls.list_known_packages",
"gopls.list_imports",
"gopls.regenerate_cgo",
"gopls.remove_dependency",
"gopls.run_tests",
"gopls.start_debugging",
"gopls.test",
"gopls.tidy",
"gopls.toggle_gc_details",
"gopls.update_go_sum",
"gopls.upgrade_dependency",
"gopls.vendor",
"gopls.workspace_metadata",
'gopls.add_dependency',
'gopls.add_import',
'gopls.apply_fix',
'gopls.check_upgrades',
'gopls.gc_details',
'gopls.generate',
'gopls.generate_gopls_mod',
'gopls.go_get_package',
'gopls.list_known_packages',
'gopls.list_imports',
'gopls.regenerate_cgo',
'gopls.remove_dependency',
'gopls.run_tests',
'gopls.start_debugging',
'gopls.test',
'gopls.tidy',
'gopls.toggle_gc_details',
'gopls.update_go_sum',
'gopls.upgrade_dependency',
'gopls.vendor',
'gopls.workspace_metadata',
}
local gopls_with_result = {
"gopls.gc_details",
"gopls.list_known_packages",
"gopls.list_imports",
'gopls.gc_details',
'gopls.list_known_packages',
'gopls.list_imports',
}
local function check_for_error(msg)
if msg ~= nil and type(msg[1]) == "table" then
if msg ~= nil and type(msg[1]) == 'table' then
for k, v in pairs(msg[1]) do
if k == "error" then
log("LSP", v.message)
if k == 'error' then
log('LSP', v.message)
break
end
end
@ -49,7 +49,7 @@ local function check_for_error(msg)
end
for _, value in ipairs(gopls_cmds) do
local fname = string.sub(value, #"gopls." + 1)
local fname = string.sub(value, #'gopls.' + 1)
cmds[fname] = function(arg)
log(fname)
local b = vim.api.nvim_get_current_buf()
@ -57,13 +57,13 @@ for _, value in ipairs(gopls_cmds) do
local arguments = { { URI = uri } }
local ft = vim.bo.filetype
if ft == "gomod" or ft == "gosum" then
if ft == 'gomod' or ft == 'gosum' then
arguments = { { URIs = { uri } } }
end
arguments = { vim.tbl_extend("keep", arguments[1], arg or {}) }
arguments = { vim.tbl_extend('keep', arguments[1], arg or {}) }
if vim.tbl_contains(gopls_with_result, value) then
local resp = vim.lsp.buf_request_sync(b, "workspace/executeCommand", {
local resp = vim.lsp.buf_request_sync(b, 'workspace/executeCommand', {
command = value,
arguments = arguments,
}, 2000)
@ -91,7 +91,7 @@ M.import = function(path)
end
M.list_imports = function(path)
path = path or vim.fn.expand("%:p")
path = path or vim.fn.expand('%:p')
local resp = cmds.list_imports({
URI = path,
})
@ -101,8 +101,8 @@ M.list_imports = function(path)
for k, val in pairs(v.result) do
result[k] = {}
for _, imp in ipairs(val) do
if imp.Name and imp.Name ~= "" then
table.insert(result[k], imp.Name .. ":" .. imp.Path)
if imp.Name and imp.Name ~= '' then
table.insert(result[k], imp.Name .. ':' .. imp.Path)
else
table.insert(result[k], imp.Path)
end
@ -132,33 +132,33 @@ end
-- check_for_upgrades({Modules = {'package'}})
function M.version()
local cache_dir = vfn.stdpath("cache")
local path = string.format("%s%sversion.txt", cache_dir, utils.sep())
local cache_dir = vfn.stdpath('cache')
local path = string.format('%s%sversion.txt', cache_dir, utils.sep())
local cfg = _GO_NVIM_CFG or {}
local gopls = cfg.gopls_cmd or { "gopls" }
local gopls = cfg.gopls_cmd or { 'gopls' }
if vfn.executable(gopls[1]) == 0 then
vim.notify("gopls not found", vim.log.levels.WARN)
vim.notify('gopls not found', vim.log.levels.WARN)
return
end
vfn.jobstart({ gopls[1], "version" }, {
vfn.jobstart({ gopls[1], 'version' }, {
on_stdout = function(_, data, _)
local msg = ""
if type(data) == "table" and #data > 0 then
data = table.concat(data, " ")
local msg = ''
if type(data) == 'table' and #data > 0 then
data = table.concat(data, ' ')
end
if #data > 1 then
msg = msg .. data
end
log(msg)
local version = string.match(msg, "%s+v([%d%.]+)%s+")
local version = string.match(msg, '%s+v([%d%.]+)%s+')
if version == nil then
log(version, msg)
return
end
local f = io.open(path, "w+")
local f = io.open(path, 'w+')
if f == nil then
return
end
@ -168,25 +168,25 @@ function M.version()
end,
})
local f = io.open(path, "r")
local f = io.open(path, 'r')
if f == nil then
local version_cmd = gopls[1] .. " version"
return vfn.system(version_cmd):match("%s+v([%d%.]+)%s+")
local version_cmd = gopls[1] .. ' version'
return vfn.system(version_cmd):match('%s+v([%d%.]+)%s+')
end
local version = f:read("*l")
local version = f:read('*l')
f:close()
log(version)
return version
end
local get_current_gomod = function()
local file = io.open("go.mod", "r")
local file = io.open('go.mod', 'r')
if file == nil then
return nil
end
local first_line = file:read()
local mod_name = first_line:gsub("module ", "")
local mod_name = first_line:gsub('module ', '')
file:close()
return mod_name
end
@ -198,16 +198,16 @@ local setups = {
completionItem = {
commitCharactersSupport = true,
deprecatedSupport = true,
documentationFormat = { "markdown", "plaintext" },
documentationFormat = { 'markdown', 'plaintext' },
preselectSupport = true,
insertReplaceSupport = true,
labelDetailsSupport = true,
snippetSupport = true,
resolveSupport = {
properties = {
"documentation",
"details",
"additionalTextEdits",
'documentation',
'details',
'additionalTextEdits',
},
},
},
@ -216,17 +216,17 @@ local setups = {
},
},
},
filetypes = { "go", "gomod", "gosum", "gotmpl", "gohtmltmpl", "gotexttmpl" },
filetypes = { 'go', 'gomod', 'gosum', 'gotmpl', 'gohtmltmpl', 'gotexttmpl' },
message_level = vim.lsp.protocol.MessageType.Error,
cmd = {
"gopls", -- share the gopls instance if there is one already
"-remote.debug=:0",
'gopls', -- share the gopls instance if there is one already
'-remote.debug=:0',
},
root_dir = function(fname)
local has_lsp, lspconfig = pcall(require, "lspconfig")
local has_lsp, lspconfig = pcall(require, 'lspconfig')
if has_lsp then
local util = lspconfig.util
return util.root_pattern("go.mod", ".git")(fname) or util.path.dirname(fname)
return util.root_pattern('go.mod', '.git')(fname) or util.path.dirname(fname)
end
end,
flags = { allow_incremental_sync = true, debounce_text_changes = 500 },
@ -259,19 +259,19 @@ local setups = {
usePlaceholders = true,
completeUnimported = true,
staticcheck = true,
matcher = "Fuzzy",
diagnosticsDelay = "500ms",
experimentalWatchedFileDelay = "200ms",
symbolMatcher = "fuzzy",
["local"] = get_current_gomod(),
matcher = 'Fuzzy',
diagnosticsDelay = '500ms',
experimentalWatchedFileDelay = '200ms',
symbolMatcher = 'fuzzy',
['local'] = get_current_gomod(),
gofumpt = _GO_NVIM_CFG.lsp_gofumpt or false, -- true|false, -- turn on for new repos, gofmpt is good but also create code turmoils
buildFlags = { "-tags", "integration" },
buildFlags = { '-tags', 'integration' },
},
},
}
local function get_build_flags()
local get_build_tags = require("go.gotest").get_build_tags
local get_build_tags = require('go.gotest').get_build_tags
local tags = get_build_tags()
log(vim.inspect(tags))
if tags then
@ -288,17 +288,17 @@ M.setups = function()
end
tags = get_build_flags()
if tags ~= "" then
setups.settings.gopls.buildFlags = {tags}
if tags ~= '' then
setups.settings.gopls.buildFlags = { tags }
end
if v > "0.7" then
setups.settings.gopls = vim.tbl_deep_extend("force", setups.settings.gopls, {
if v > '0.7' then
setups.settings.gopls = vim.tbl_deep_extend('force', setups.settings.gopls, {
experimentalUseInvalidMetadata = true,
-- hoverKind = "Structured",
})
end
if v > "0.9" and _GO_NVIM_CFG.lsp_inlay_hints.enable then
setups.settings.gopls = vim.tbl_deep_extend("force", setups.settings.gopls, {
if v > '0.9' and _GO_NVIM_CFG.lsp_inlay_hints.enable then
setups.settings.gopls = vim.tbl_deep_extend('force', setups.settings.gopls, {
hints = {
assignVariableTypes = true,
compositeLiteralFields = true,

@ -80,7 +80,6 @@ local guru_cmd = function(args)
if not data then
return
end
print(data)
log(data)
local res = data
if format == "json" then

@ -214,4 +214,161 @@ M.codelens_enabled = function()
return codelens_enabled
end
local function request(method, params, handler)
return vim.lsp.buf_request(0, method, params, handler)
end
function M.gen_return(lsp_result)
if not lsp_result or not lsp_result.contents then
return
end
local contents = vim.split(lsp_result.contents.value, '\n')
local func
for _, line in ipairs(contents) do
if line:match('^func') then
func = line
break
end
end
if not func then
return
end
local ret_list, err = M.find_ret(func)
if ret_list == nil or next(ret_list) == nil then
return
end
local header = ret_list[1]
for i = 2, #ret_list do
header = header .. ', ' .. ret_list[i]
end
local current_line = vim.api.nvim_get_current_line()
local ss, se = string.find(current_line, '%s+')
local leading_space = ''
if ss then
leading_space = current_line:sub(ss, se)
end
header = leading_space .. header .. ' := ' .. vim.trim(current_line)
local row, col = unpack(api.nvim_win_get_cursor(0))
vim.api.nvim_buf_set_lines(0, row - 1, row, true, { header })
vim.cmd('write')
if err then
require('go.iferr').run()
end
return header
end
local name_map = {
error = 'err',
int = 'i',
int64 = 'i',
uint = 'i',
uint64 = 'i',
float = 'f',
float64 = 'f',
string = 's',
rune = 'r',
bool = 'b',
channel = 'ch',
byte = 'b',
}
function gen_name(types)
local rets = {}
local used = {}
for _, t in pairs(types) do
if name_map[t] then
if not used[name_map[t]] then
rets[#rets + 1] = name_map[t]
used[name_map[t]] = 1
else
rets[#rets + 1] = name_map[t] .. tostring(used[name_map[t]])
used[name_map[t]] = used[name_map[t]] + 1
end
else
local f = t:sub(1, 1)
if f == f:upper() then
name_map[t] = f:lower() .. t:sub(2)
table.insert(rets, name_map[t])
used[name_map[t]] = (used[name_map[t]] or 0) + 1
else
name_map[t] = f
table.insert(rets, name_map[t])
used[name_map[t]] = (used[name_map[t]] or 0) + 1
end
end
end
log(rets)
return rets
end
function M.find_ret(str)
str = vim.trim(str)
local pat = [[\v^func\s+%(\w|\.)+\(%(\w|\_s|[*\.\[\],{}<>-])*\)\s+]]
local regex = vim.regex(pat)
local start, endpos = regex:match_str(str)
if start == nil then
return
end
local ret = vim.trim(str:sub(endpos + 1))
if ret == '' then
return
end
pat = [[\v\(%(\w|\_s|[*\.\[\],{}<>-])*\)]]
regex = vim.regex(pat)
start, endpos = regex:match_str(ret)
-- handle return type in bracket
local retlist = {}
if start ~= nil then
ret = ret:sub(2, #ret - 1) -- remove ( and )
local ret_types = vim.split(ret, ',%s*')
local need_convert = true
for _, t in pairs(ret_types) do
t = vim.trim(t)
local m = vim.split(t, '%s+')
if #m > 1 then
need_convert = false
end
table.insert(retlist, m[1])
end
if need_convert then
retlist = gen_name(ret_types)
end
else
retlist = gen_name({ ret })
end
local includes_err = vim.tbl_contains(retlist, 'err')
return retlist, includes_err
end
function M.hover_returns()
local util = require('vim.lsp.util')
local current_line = vim.api.nvim_get_current_line()
local row, col = unpack(api.nvim_win_get_cursor(0))
local pat = [[\w\+(]]
local r = vim.regex(pat)
local s, e = r:match_str(current_line)
log(s, e)
if s == nil then
return
end
local params = util.make_position_params()
params.position.character = e - 1
log(params)
request('textDocument/hover', params, function(err, result, ctx)
if err ~= nil then
log(err)
return
end
if result == nil then
return
end
M.gen_return(result)
end)
end
return M

@ -4,7 +4,8 @@ local ts_query = vim.treesitter.query
local ts_utils = require("nvim-treesitter.ts_utils")
local util = require("go.utils")
local log = util.log
local trace = util.log
local trace = util.trace
-- local trace = util.log
local M = {}
-- local ulog = require("go.utils").log
@ -105,9 +106,13 @@ end
function M.list_definitions_toc(bufnr)
bufnr = bufnr or api.nvim_win_get_buf(api.nvim_get_current_win())
vim.api.nvim_buf_set_option(bufnr, "filetype", "go")
vim.api.nvim_buf_set_option(bufnr, "syntax", "enable")
log('get_definitions', bufnr)
local definitions = get_definitions(bufnr)
log("definitions: ", definitions)
if #definitions < 1 then
log('unable to find definitions')
return
end

@ -42,11 +42,6 @@ local function filter(prefix)
end
ls.add_snippets("all", {
ls.s("dl1", {
ls.i(1, "sample_text"),
ls.t({ ":", "" }),
dl(2, l._1, 1),
}),
ls.s("time", partial(vim.fn.strftime, "%H:%M:%S")),
ls.s("date", partial(vim.fn.strftime, "%Y-%m-%d")),
ls.s("pwd", { partial(utils.run_command, "pwd") }),

@ -1,43 +1,41 @@
local _ = require("plenary/busted")
local _ = require('plenary/busted')
print('aaa')
local eq = assert.are.same
local cur_dir = vim.fn.expand("%:p:h")
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 fixplurals", function()
describe('should run fixplurals', 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 run fixplurals", function()
it('should run fixplurals', function()
--
local name = vim.fn.tempname() .. ".go"
local path = cur_dir .. "/lua/tests/fixtures/fixplurals/fixp_input.go" -- %:p:h ? %:p
local name = vim.fn.tempname() .. '.go'
local path = cur_dir .. '/lua/tests/fixtures/fixplurals/fixp_input.go' -- %:p:h ? %:p
local lines = vim.fn.readfile(path)
vim.fn.writefile(lines, name)
local expected = vim.fn.join(vim.fn.readfile(cur_dir
.. "/lua/tests/fixtures/fixplurals/fixp_golden.go"),
"\n")
local expected = vim.fn.join(vim.fn.readfile(cur_dir .. '/lua/tests/fixtures/fixplurals/fixp_golden.go'), '\n')
local cmd = " silent exe 'e " .. name .. "'"
vim.cmd(cmd)
local bufn = vim.fn.bufnr("")
local bufn = vim.fn.bufnr('')
vim.fn.setpos(".", {bufn, 2, 11, 0})
vim.fn.setpos('.', { bufn, 2, 11, 0 })
-- local l = vim.api.nvim_buf_get_lines(0, 0, -1, true)
vim.bo.filetype = "go"
vim.bo.filetype = 'go'
local gofixp = require("go.fixplurals")
local gofixp = require('go.fixplurals')
gofixp.fixplurals()
vim.wait(100, function()
vim.cmd('w')
vim.cmd('w')
end)
local fmt = vim.fn.join(vim.fn.readfile(name), "\n")
local fmt = vim.fn.join(vim.fn.readfile(name), '\n')
vim.fn.assert_equal(fmt, expected)
eq(expected, fmt)
cmd = "bd! " .. name
cmd = 'bd! ' .. name
vim.cmd(cmd)
end)
end)

@ -0,0 +1,91 @@
local eq = assert.are.same
local cur_dir = vim.fn.expand('%:p:h')
-- func Println(a ...any) (n int, err error)
-- func fmt.Println(a ...any) (n int, err error)
-- func fmt.inner.Println(a ...any) (n int, err error)
-- func fmt.inner2.Println3(a ...any) (n int, err error)
-- func fmt.inner2.Println3(a any, par int) (n int, err error)
-- func fmt.inner2.Println3(a any, par int) int
-- func fmt.inner2.Println3(par int) int
-- func fmt.inner2.Println3(par int)
-- func fmt.inner2.Println3(par *[]int)
-- func fmt.inner2.Println3(par struct mnt{})
-- /(\%(\w\|\_s\|[*\.\[\],\{\}<>-]\)*)/
-- /\v\((\w|\_s|[*\.\[\],{}<>-])*\)
local busted = require('plenary/busted')
describe('regex should work', function()
-- vim.fn.readfile('minimal.vim')
-- vim.fn.writefile(vim.fn.readfile('fixtures/fmt/hello.go'), name)
require('plenary.reload').reload_module('go.nvim')
require('go').setup({
trace = true,
log_path = vim.fn.expand('$HOME') .. '/tmp/gonvim.log',
})
print(vim.fn.expand('$HOME') .. '/tmp/gonvim.log')
it('should find return', function()
local str = [[func Println(a ...any) (n int, err error)]]
local ret = require('go.lsp').find_ret(str)
print(vim.inspect(ret))
eq({'n', 'err'}, ret)
end)
it('should find return', function()
local str = [[func fmt.Println(a ...any) (int, error)]]
local ret, e = require('go.lsp').find_ret(str)
print(vim.inspect(ret))
eq({'i', 'err'}, ret)
eq(true, e)
end)
it('should find return', function()
local str = [[func fmt.Println(a, b int) (int, error)]]
local ret, e = require('go.lsp').find_ret(str)
print(vim.inspect(ret))
eq({'i', 'err'}, ret)
eq(true, e)
end)
it('should find return', function()
local str = [[func fmt.Println(a, b int) int]]
local ret, e = require('go.lsp').find_ret(str)
print(vim.inspect(ret))
eq({'i'}, ret)
eq(false, e)
end)
it('should find return', function()
local str = [[func fmt.Println(a, b int) MyType]]
local ret, e = require('go.lsp').find_ret(str)
print(vim.inspect(ret))
eq({'myType'}, ret)
eq(false, e)
end)
it('should find return', function()
local str = [[func fmt.Println(a, b int) (MyType, error)]]
local ret, e = require('go.lsp').find_ret(str)
print(vim.inspect(ret))
eq({'myType', 'err'}, ret)
eq(true, e)
end)
end)
describe('should run hover', function()
-- vim.fn.readfile('minimal.vim')
-- vim.fn.writefile(vim.fn.readfile('fixtures/fmt/hello.go'), name)
require('plenary.reload').reload_module('go.nvim')
it('should run hover', function()
local result = {
contents = {
kind = 'markdown',
value = [[```go\nfunc fmt.Println(a ...any) (n int, err error)(\%(\w\|\_s\|[*\.\[\],\{\}<>-]\)*)\n```\n\nPrintln formats using the default formats for its operands and writes to standard output\\.\nSpaces are always added between operands and a newline is appended\\.\nIt returns the number of bytes written and any write error encountered\\.\n\n\n[`fmt.Println` on pkg.go.dev](https://pkg.go.dev/fmt?utm_source=gopls#Println)]],
},
range = {},
}
local ret = require('go.lsp').gen_return(result)
print(vim.inspect(ret))
end)
end)

@ -1,4 +0,0 @@
[
(composite_literal)
(literal_element)
] @fold
Loading…
Cancel
Save