go.nvim/lua/go/gopls.lua

329 lines
8.5 KiB
Lua
Raw Normal View History

2022-08-23 09:31:13 +00:00
local utils = require('go.utils')
2021-11-11 02:01:14 +00:00
local log = utils.log
2022-06-01 11:29:13 +00:00
local vfn = vim.fn
2021-11-11 02:01:14 +00:00
local M = {}
2022-04-18 12:31:17 +00:00
local cmds = {}
2021-11-11 02:01:14 +00:00
-- https://go.googlesource.com/tools/+/refs/heads/master/gopls/doc/commands.md
-- "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 = {
2022-08-23 09:31:13 +00:00
'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',
2021-11-11 02:01:14 +00:00
}
2022-04-18 12:31:17 +00:00
local gopls_with_result = {
2022-08-23 09:31:13 +00:00
'gopls.gc_details',
'gopls.list_known_packages',
'gopls.list_imports',
2022-04-18 12:31:17 +00:00
}
2021-11-11 02:01:14 +00:00
local function check_for_error(msg)
2022-08-23 09:31:13 +00:00
if msg ~= nil and type(msg[1]) == 'table' then
2021-11-11 02:01:14 +00:00
for k, v in pairs(msg[1]) do
2022-08-23 09:31:13 +00:00
if k == 'error' then
log('LSP', v.message)
2021-11-11 02:01:14 +00:00
break
end
end
end
end
for _, value in ipairs(gopls_cmds) do
2022-08-23 09:31:13 +00:00
local fname = string.sub(value, #'gopls.' + 1)
2022-04-18 12:31:17 +00:00
cmds[fname] = function(arg)
2021-11-11 02:01:14 +00:00
local b = vim.api.nvim_get_current_buf()
local uri = vim.uri_from_bufnr(b)
2022-04-18 12:31:17 +00:00
local arguments = { { URI = uri } }
local ft = vim.bo.filetype
2022-08-23 09:31:13 +00:00
if ft == 'gomod' or ft == 'gosum' then
2022-04-18 12:31:17 +00:00
arguments = { { URIs = { uri } } }
end
2022-08-23 09:31:13 +00:00
arguments = { vim.tbl_extend('keep', arguments[1], arg or {}) }
2021-11-11 02:01:14 +00:00
log(fname, arguments)
2022-04-18 12:31:17 +00:00
if vim.tbl_contains(gopls_with_result, value) then
2022-08-23 09:31:13 +00:00
local resp = vim.lsp.buf_request_sync(b, 'workspace/executeCommand', {
2022-04-18 12:31:17 +00:00
command = value,
arguments = arguments,
}, 2000)
check_for_error(resp)
log(resp)
return resp
end
vim.schedule(function()
local resp = vim.lsp.buf.execute_command({
command = value,
arguments = arguments,
})
check_for_error(resp)
log(resp)
end)
2021-11-11 02:01:14 +00:00
end
end
M.cmds = cmds
2022-04-18 12:31:17 +00:00
M.import = function(path)
cmds.add_import({
ImportPath = path,
})
end
2022-06-16 04:10:49 +00:00
M.list_imports = function(path)
2022-08-23 09:31:13 +00:00
path = path or vim.fn.expand('%:p')
2022-06-16 04:10:49 +00:00
local resp = cmds.list_imports({
URI = path,
})
2022-07-26 16:21:58 +00:00
local result = {}
2022-06-16 04:10:49 +00:00
for _, v in pairs(resp) do
if v.result then
for k, val in pairs(v.result) do
result[k] = {}
for _, imp in ipairs(val) do
2022-08-23 09:31:13 +00:00
if imp.Name and imp.Name ~= '' then
table.insert(result[k], imp.Name .. ':' .. imp.Path)
2022-06-16 04:10:49 +00:00
else
table.insert(result[k], imp.Path)
end
end
end
end
end
return result, resp
end
2021-11-13 03:29:42 +00:00
M.list_pkgs = function()
2022-04-18 12:31:17 +00:00
local resp = cmds.list_known_packages() or {}
2021-11-13 03:29:42 +00:00
local pkgs = {}
for _, response in pairs(resp) do
if response.result ~= nil then
pkgs = response.result.Packages
break
end
end
return pkgs
end
2022-05-15 04:09:07 +00:00
M.tidy = function()
cmds.tidy()
end
2021-11-11 02:01:14 +00:00
-- check_for_upgrades({Modules = {'package'}})
function M.version()
2022-08-23 09:31:13 +00:00
local cache_dir = vfn.stdpath('cache')
local path = string.format('%s%sversion.txt', cache_dir, utils.sep())
2022-05-13 10:54:47 +00:00
local cfg = _GO_NVIM_CFG or {}
2022-08-23 09:31:13 +00:00
local gopls = cfg.gopls_cmd or { 'gopls' }
2022-04-30 01:57:51 +00:00
2022-06-01 11:29:13 +00:00
if vfn.executable(gopls[1]) == 0 then
2022-08-23 09:31:13 +00:00
vim.notify('gopls not found', vim.log.levels.WARN)
2022-04-30 01:57:51 +00:00
return
end
2022-08-23 09:31:13 +00:00
vfn.jobstart({ gopls[1], 'version' }, {
2022-06-01 11:29:13 +00:00
on_stdout = function(_, data, _)
2022-08-23 09:31:13 +00:00
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)
2022-08-23 09:31:13 +00:00
local version = string.match(msg, '%s+v([%d%.]+)%s+')
if version == nil then
log(version, msg)
return
end
2022-08-23 09:31:13 +00:00
local f = io.open(path, 'w+')
if f == nil then
return
end
f:write(version)
f:close()
log(version)
end,
})
2022-08-23 09:31:13 +00:00
local f = io.open(path, 'r')
if f == nil then
2022-08-23 09:31:13 +00:00
local version_cmd = gopls[1] .. ' version'
return vfn.system(version_cmd):match('%s+v([%d%.]+)%s+')
end
2022-08-23 09:31:13 +00:00
local version = f:read('*l')
f:close()
log(version)
return version
end
2022-07-19 23:27:59 +00:00
local get_current_gomod = function()
2022-08-23 09:31:13 +00:00
local file = io.open('go.mod', 'r')
2022-07-19 23:27:59 +00:00
if file == nil then
return nil
end
local first_line = file:read()
2022-08-23 09:31:13 +00:00
local mod_name = first_line:gsub('module ', '')
2022-07-19 23:27:59 +00:00
file:close()
return mod_name
end
local function get_build_flags()
2022-08-23 09:31:13 +00:00
local get_build_tags = require('go.gotest').get_build_tags
2022-08-08 05:56:59 +00:00
local tags = get_build_tags()
log(vim.inspect(tags))
if tags then
return tags
else
return nil
end
end
M.setups = function()
local setups = {
capabilities = {
textDocument = {
completion = {
completionItem = {
commitCharactersSupport = true,
deprecatedSupport = true,
documentationFormat = { 'markdown', 'plaintext' },
preselectSupport = true,
insertReplaceSupport = true,
labelDetailsSupport = true,
snippetSupport = true,
resolveSupport = {
properties = {
'documentation',
'details',
'additionalTextEdits',
},
},
},
contextSupport = true,
dynamicRegistration = true,
},
},
},
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',
},
root_dir = function(fname)
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)
end
end,
flags = { allow_incremental_sync = true, debounce_text_changes = 500 },
settings = {
gopls = {
-- more settings: https://github.com/golang/tools/blob/master/gopls/doc/settings.md
-- not supported
analyses = {
unreachable = true,
nilness = true,
unusedparams = true,
useany = true,
unusedwrite = true,
ST1003 = true,
undeclaredname = true,
fillreturns = true,
nonewvars = true,
fieldalignment = false,
shadow = true,
},
codelenses = {
generate = true, -- show the `go generate` lens.
gc_details = true, -- Show a code lens toggling the display of gc's choices.
test = true,
tidy = true,
vendor = true,
regenerate_cgo = true,
upgrade_dependency = true,
},
usePlaceholders = true,
completeUnimported = true,
staticcheck = true,
matcher = 'Fuzzy',
diagnosticsDelay = '500ms',
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' },
},
},
}
local v = M.version()
2022-04-30 01:57:51 +00:00
if v == nil then
return
end
2022-10-31 23:54:24 +00:00
v = vim.fn.split(v, '\\D')
local ver = 0
2022-11-28 14:29:45 +00:00
for _, n in ipairs(v) do
ver = (ver * 10 + tonumber(n)) or 0
2022-10-31 23:54:24 +00:00
end
2022-11-28 14:29:45 +00:00
local tags = get_build_flags()
2022-08-23 09:31:13 +00:00
if tags ~= '' then
setups.settings.gopls.buildFlags = { tags }
end
2022-10-31 23:54:24 +00:00
if ver > 70 and ver < 100 then
2022-08-23 09:31:13 +00:00
setups.settings.gopls = vim.tbl_deep_extend('force', setups.settings.gopls, {
experimentalUseInvalidMetadata = true,
2022-07-22 12:18:53 +00:00
-- hoverKind = "Structured",
})
end
2022-10-31 23:54:24 +00:00
if ver > 80 and ver < 100 then
setups.settings.gopls = vim.tbl_deep_extend('force', setups.settings.gopls, {
experimentalWatchedFileDelay = '200ms',
})
end
if ver > 90 and _GO_NVIM_CFG.lsp_inlay_hints.enable then
2022-08-23 09:31:13 +00:00
setups.settings.gopls = vim.tbl_deep_extend('force', setups.settings.gopls, {
2022-07-19 23:27:59 +00:00
hints = {
assignVariableTypes = true,
compositeLiteralFields = true,
compositeLiteralTypes = true,
constantValues = true,
functionTypeParameters = true,
parameterNames = true,
rangeVariableTypes = true,
},
})
end
return setups
end
2021-11-11 02:01:14 +00:00
return M