diff options
| author | Benjamin Alpert <benjamin.alpert@t-systems.com> | 2025-07-09 03:22:20 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-08 18:22:20 -0700 |
| commit | 592916db3f4ecdf062962b3aa83583aebe3c4a14 (patch) | |
| tree | 7f2845c8720b55c0521f6e27119fe59983c3a829 /lsp/gopls.lua | |
| parent | feat(ts_ls): implement codelens support #3938 (diff) | |
| download | nvim-lspconfig-592916db3f4ecdf062962b3aa83583aebe3c4a14.tar nvim-lspconfig-592916db3f4ecdf062962b3aa83583aebe3c4a14.tar.gz nvim-lspconfig-592916db3f4ecdf062962b3aa83583aebe3c4a14.tar.bz2 nvim-lspconfig-592916db3f4ecdf062962b3aa83583aebe3c4a14.tar.lz nvim-lspconfig-592916db3f4ecdf062962b3aa83583aebe3c4a14.tar.xz nvim-lspconfig-592916db3f4ecdf062962b3aa83583aebe3c4a14.tar.zst nvim-lspconfig-592916db3f4ecdf062962b3aa83583aebe3c4a14.zip | |
feat(gopls): refactor root_dir identification #3942
Refactor the logic on how to identify the root_dir for gopls. This will
provide a viable solution to the issue where multiple gopls lsp client
instances are started, causing adverse effects in certain areas like
diagnostics, lsp functionality (such as `go to definition`,
workspace-enabled projects). The identification for required directories
are based on golang-specific environment variables which are set by
default.
Diffstat (limited to 'lsp/gopls.lua')
| -rw-r--r-- | lsp/gopls.lua | 91 |
1 files changed, 72 insertions, 19 deletions
diff --git a/lsp/gopls.lua b/lsp/gopls.lua index fd22ff0d..0b4c59f6 100644 --- a/lsp/gopls.lua +++ b/lsp/gopls.lua @@ -4,13 +4,80 @@ --- --- Google's lsp server for golang. +--- @class go_dir_custom_args +--- +--- @field envvar_id string +--- +--- @field custom_subdir string? + local mod_cache = nil +local std_lib = nil + +---@param custom_args go_dir_custom_args +---@param on_complete fun(dir: string | nil) +local function identify_go_dir(custom_args, on_complete) + local cmd = { 'go', 'env', custom_args.envvar_id } + vim.system(cmd, { text = true }, function(output) + local res = vim.trim(output.stdout or '') + if output.code == 0 and res ~= '' then + if custom_args.custom_subdir and custom_args.custom_subdir ~= '' then + res = res .. custom_args.custom_subdir + end + on_complete(res) + else + vim.schedule(function() + vim.notify( + ('[gopls] identify ' .. custom_args.envvar_id .. ' dir cmd failed with code %d: %s\n%s'):format( + output.code, + vim.inspect(cmd), + output.stderr + ) + ) + end) + on_complete(nil) + end + end) +end + +---@return string? +local function get_std_lib_dir() + if std_lib and std_lib ~= '' then + return std_lib + end + + identify_go_dir({ envvar_id = 'GOROOT', custom_subdir = '/src' }, function(dir) + if dir then + std_lib = dir + end + end) + return std_lib +end + +---@return string? +local function get_mod_cache_dir() + if mod_cache and mod_cache ~= '' then + return mod_cache + end + + identify_go_dir({ envvar_id = 'GOMODCACHE' }, function(dir) + if dir then + mod_cache = dir + end + end) + return mod_cache +end ---@param fname string ---@return string? -local function get_root(fname) +local function get_root_dir(fname) if mod_cache and fname:sub(1, #mod_cache) == mod_cache then - local clients = vim.lsp.get_clients { name = 'gopls' } + local clients = vim.lsp.get_clients({ name = 'gopls' }) + if #clients > 0 then + return clients[#clients].config.root_dir + end + end + if std_lib and fname:sub(1, #std_lib) == std_lib then + local clients = vim.lsp.get_clients({ name = 'gopls' }) if #clients > 0 then return clients[#clients].config.root_dir end @@ -23,23 +90,9 @@ return { filetypes = { 'go', 'gomod', 'gowork', 'gotmpl' }, root_dir = function(bufnr, on_dir) local fname = vim.api.nvim_buf_get_name(bufnr) + get_mod_cache_dir() + get_std_lib_dir() -- see: https://github.com/neovim/nvim-lspconfig/issues/804 - if mod_cache then - on_dir(get_root(fname)) - return - end - local cmd = { 'go', 'env', 'GOMODCACHE' } - vim.system(cmd, { text = true }, function(output) - if output.code == 0 then - if output.stdout then - mod_cache = vim.trim(output.stdout) - end - on_dir(get_root(fname)) - else - vim.schedule(function() - vim.notify(('[gopls] cmd failed with code %d: %s\n%s'):format(output.code, cmd, output.stderr)) - end) - end - end) + on_dir(get_root_dir(fname)) end, } |
