local vim, api = vim, vim.api local utils = require('go.utils') local log = utils.log local diagnostic_map = function(bufnr) local opts = {noremap = true, silent = true} api.nvim_buf_set_keymap(bufnr, "n", "]O", ":lua vim.lsp.diagnostic.set_loclist()", opts) end local on_attach = function(client, bufnr) if _GO_NVIM_CFG.lsp_on_attach then if type(_GO_NVIM_CFG.lsp_on_attach) == "function" then _GO_NVIM_CFG.lsp_on_attach(client, bufnr) return end end local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end local uri = vim.uri_from_bufnr(bufnr) if uri == "file://" or uri == "file:///" or #uri < 11 then return {error = "invalid file", result = nil} end diagnostic_map(bufnr) -- add highlight for Lspxxx api.nvim_buf_set_option(bufnr, "omnifunc", "v:lua.vim.lsp.omnifunc") local opts = {noremap = true, silent = true} buf_set_keymap('n', 'gD', 'lua vim.lsp.buf.declaration()', opts) buf_set_keymap('n', 'gd', 'lua vim.lsp.buf.definition()', opts) buf_set_keymap('n', 'K', 'lua vim.lsp.buf.hover()', opts) buf_set_keymap('n', 'gi', 'lua vim.lsp.buf.implementation()', opts) buf_set_keymap('n', '', 'lua vim.lsp.buf.signature_help()', opts) buf_set_keymap('n', 'wa', 'lua vim.lsp.buf.add_workspace_folder()', opts) buf_set_keymap('n', 'wr', 'lua vim.lsp.buf.remove_workspace_folder()', opts) buf_set_keymap('n', 'wl', 'lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))', opts) buf_set_keymap('n', 'D', 'lua vim.lsp.buf.type_definition()', opts) buf_set_keymap('n', 'rn', 'lua vim.lsp.buf.rename()', opts) buf_set_keymap('n', 'ca', 'lua vim.lsp.buf.code_action()', opts) buf_set_keymap('n', 'gr', 'lua vim.lsp.buf.references()', opts) buf_set_keymap('n', 'e', 'lua vim.lsp.diagnostic.show_line_diagnostics()', opts) buf_set_keymap('n', '[d', 'lua vim.lsp.diagnostic.goto_prev()', opts) buf_set_keymap('n', ']d', 'lua vim.lsp.diagnostic.goto_next()', opts) buf_set_keymap('n', 'q', 'lua vim.lsp.diagnostic.set_loclist()', opts) buf_set_keymap("n", "f", "lua vim.lsp.buf.formatting()", opts) buf_set_keymap("n", "ff", "lua vim.lsp.buf.formatting()", opts) end local gopls = { -- capabilities = cap, filetypes = {"go", "gomod"}, message_level = vim.lsp.protocol.MessageType.Error, cmd = { "gopls", -- share the gopls instance if there is one already "-remote.debug=:0" }, flags = {allow_incremental_sync = true, debounce_text_changes = 500}, settings = { gopls = { -- more settings: https://github.com/golang/tools/blob/master/gopls/doc/settings.md -- flags = {allow_incremental_sync = true, debounce_text_changes = 500}, -- not supported analyses = {unusedparams = true, unreachable = false}, 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 }, usePlaceholders = true, completeUnimported = true, staticcheck = true, matcher = "Fuzzy", -- experimentalDiagnosticsDelay = "500ms", diagnosticsDelay = "500ms", experimentalWatchedFileDelay = "100ms", symbolMatcher = "fuzzy", ['local'] = "", gofumpt = false, -- true, -- turn on for new repos, gofmpt is good but also create code turmoils buildFlags = {"-tags", "integration"} -- buildFlags = {"-tags", "functional"} } } } local extend_config = function(opts) opts = opts or {} if next(opts) == nil then return end for key, value in pairs(opts) do if type(gopls[key]) == "table" then for k, v in pairs(value) do gopls[key][k] = v end else gopls[key] = value end end end local M = {} function M.setup() if _GO_NVIM_CFG.lsp_on_attach then if _GO_NVIM_CFG.lsp_on_attach == true then gopls.on_attach = on_attach else gopls.on_attach = _GO_NVIM_CFG.lsp_on_attach end end if _GO_NVIM_CFG.gopls_cmd then gopls.cmd = _GO_NVIM_CFG.gopls_cmd else gopls.cmd = {'gopls'} end if _GO_NVIM_CFG.lsp_gofumpt then gopls.settings.gopls.gofumpt = true end if _GO_NVIM_CFG.gopls_remote_auto then table.insert(gopls.cmd, "-remote=auto") end if type(_GO_NVIM_CFG.lsp_cfg) == "table" then extend_config(_GO_NVIM_CFG.lsp_cfg) end log(gopls) require'lspconfig'.gopls.setup(gopls) end --[[ FillStruct = "fill_struct" UndeclaredName = "undeclared_name" ExtractVariable = "extract_variable" ExtractFunction = "extract_function" ExtractMethod = "extract_method" valueSet = { "", "Empty", "QuickFix", "Refactor", "RefactorExtract", "RefactorInline", "RefactorRewrite", "Source", "SourceOrganizeImports", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.re write", "source", "source.organizeImports" } ]] -- action / fix to take -- only this action 'refactor.rewrite' source.organizeImports M.codeaction = function(action, only, wait_ms) wait_ms = wait_ms or 1000 local params = vim.lsp.util.make_range_params() log(action, only) if only then params.context = {only = {only}} end local result = vim.lsp.buf_request_sync(0, "textDocument/codeAction", params, wait_ms) if not result or next(result) == nil then log("nil result") return end log("code action result", result) for _, res in pairs(result) do for _, r in pairs(res.result or {}) do if r.edit and not vim.tbl_isempty(r.edit) then local result = vim.lsp.util.apply_workspace_edit(r.edit) log("workspace edit", r) end if type(r.command) == "table" then if type(r.command) == "table" and r.command.arguments then for _, arg in pairs(r.command.arguments) do if action == nil or arg['Fix'] == action then vim.lsp.buf.execute_command(r.command) return end end end end end end end return M