Skip to content

x/tools/gopls: v0.16.1 breaking omnifunc completion in neovim #68764

Closed
@abennett

Description

@abennett

gopls version

Build info
----------
golang.org/x/tools/gopls v0.16.1
    golang.org/x/tools/gopls@v0.16.1 h1:1hO/dCeUvjEYx3V0rVvCtOkwnpEpqS29paE+Jw4dcAc=
    github.com/BurntSushi/toml@v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
    github.com/google/go-cmp@v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
    golang.org/x/exp/typeparams@v0.0.0-20221212164502-fae10dda9338 h1:2O2DON6y3XMJiQRAS1UWU+54aec2uopH3x7MAiqGW6Y=
    golang.org/x/mod@v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
    golang.org/x/sync@v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
    golang.org/x/telemetry@v0.0.0-20240607193123-221703e18637 h1:3Wt8mZlbFwG8llny+t18kh7AXxyWePFycXMuVdHxnyM=
    golang.org/x/text@v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
    golang.org/x/tools@v0.22.1-0.20240628205440-9c895dd76b34 h1:Kd+Z5Pm6uwYx3T2KEkeHMHUMZxDPb/q6b1m+zEcy62c=
    golang.org/x/vuln@v1.0.4 h1:SP0mPeg2PmGCu03V+61EcQiOjmpri2XijexKdzv8Z1I=
    honnef.co/go/tools@v0.4.7 h1:9MDAWxMoSnB6QoSqiVr7P5mtkT9pOc1kSxchzPCnqJs=
    mvdan.cc/gofumpt@v0.6.0 h1:G3QvahNDmpD+Aek/bNOLrFR2XC6ZAdo62dZu65gmwGo=
    mvdan.cc/xurls/v2@v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=
go: go1.22.5

go env

GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/aaron/Library/Caches/go-build'
GOENV='/Users/aaron/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/aaron/go/pkg/mod'
GOOS='darwin'
GOPATH='/Users/aaron/go'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.22.5/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.22.5/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.22.5'
GCCGO='gccgo'
AR='ar'
CC='cc'
CXX='c++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/5p/fpck_9g5367f7lk3p50bvdbc0000gn/T/go-build356802509=/tmp/go-build -gno-record-gcc-switches -fno-common

What did you do?

  1. Upgrade gopls to v0.16.1.
  2. Open a Go file with neovim.
  3. Attempt to use omnifunc completion with <ctrl-x><ctrl-o>
  4. neovim throws an indexing error
  5. Reverting back to gopls version v0.15.3 works as expected.

What did you see happen?

Attempting to use omnifunc completion with <ctrl-x><ctrl-o> result in the following indexing error from neovim.

Error executing vim.schedule lua callback: ...im/0.10.1/share/nvim/runtime/lua/vim/lsp/_completion.lua:154: attempt to index field 'range' (a nil value)                                                                                                                      
stack traceback:                                                                                                                                                                                                                                                                        
        ...im/0.10.1/share/nvim/runtime/lua/vim/lsp/_completion.lua:154: in function 'adjust_start_col'                                                                                                                                                                                 
        ...im/0.10.1/share/nvim/runtime/lua/vim/lsp/_completion.lua:202: in function '_convert_results'                                                                                                                                                                                 
        ...im/0.10.1/share/nvim/runtime/lua/vim/lsp/_completion.lua:253: in function 'handler'                                                                                                                                                                                          
        .../neovim/0.10.1/share/nvim/runtime/lua/vim/lsp/client.lua:687: in function ''                                                                                                                                                                                                 
        vim/_editor.lua: in function <vim/_editor.lua:0> 

What did you expect to see?

Successful autocompletion recommendations without an error.

Editor and settings

Running neovim version v0.10.1.

-- Set leader
vim.g.mapleader = ","

-- Plug-Ins below
-- Bootstrap lazy.nvim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
  local lazyrepo = "https://github.com/folke/lazy.nvim.git"
  local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath })
  if vim.v.shell_error ~= 0 then
    vim.api.nvim_echo({
      { "Failed to clone lazy.nvim:\n", "ErrorMsg" },
      { out, "WarningMsg" },
      { "\nPress any key to exit..." },
    }, true, {})
    vim.fn.getchar()
    os.exit(1)
  end
end
vim.opt.rtp:prepend(lazypath)

local plugins = {
  {
    'catppuccin/nvim',
    lazy = false,
    priority = 1000,
    config = function()
      vim.cmd([[colorscheme catppuccin]])
    end,
  },
  'neovim/nvim-lspconfig',
  'windwp/nvim-autopairs',
  {
    'nvim-lualine/lualine.nvim',
    dependencies = {'nvim-tree/nvim-web-devicons'},
  },
  'mattn/emmet-vim',
  {
    'nvim-treesitter/nvim-treesitter',
    cmd = {"TSUpdateSync"},
  },
  'ray-x/lsp_signature.nvim',
  {
    'lukas-reineke/indent-blankline.nvim',
    main = "ibl",
  },
  'glench/vim-jinja2-syntax',
  'tsandall/vim-rego',
  'lewis6991/gitsigns.nvim',

  --  auto completion,
  {
    'hrsh7th/nvim-cmp',
    dependencies = {
      'hrsh7th/cmp-nvim-lsp',
      'hrsh7th/cmp-buffer',
      'hrsh7th/cmp-path',
      'hrsh7th/cmp-cmdline',
    }
  },

  'hrsh7th/cmp-vsnip',
  'hrsh7th/vim-vsnip',
}

require("lazy").setup({
    spec = plugins,
})

require('catppuccin').setup {
  flavor = "mocha"
}

-- treesitter
require('nvim-treesitter.configs').setup {
  ensure_installed = "all",
  ignore_install = { "phpdoc" },
  highlight = {
    enable = true,
  },
  indent = {
    enable = true
  },
  additional_vim_regex_highlighting = false,
}

-- completion
local cmp = require('cmp')
cmp.setup({
  snippet = {
    expand = function(args)
      vim.fn["vsnip#anonymous"](args.body)
    end
  },
  mapping = cmp.mapping.preset.insert({
    ['<C-b>'] = cmp.mapping.scroll_docs(-4),
    ['<C-f>'] = cmp.mapping.scroll_docs(4),
    ['<C-Space>'] = cmp.mapping.complete(),
    ['<C-e>'] = cmp.mapping.abort(),
    ['<CR>'] = cmp.mapping.confirm({ select = true }),
  }),
  sources = cmp.config.sources({
    { name = "nvim_lsp" },
    { name = "vsnip" },
  }, {
      { name = "buffer" },
  })
})

-- indent guides
require('ibl').setup()

-- lualine
require('lualine').setup()

-- gitsigns
require('gitsigns').setup()

-- autopairs
require('nvim-autopairs').setup()

-- Use an on_attach function to only map the following keys
-- after the language server attaches to the current buffer
local on_attach = function(client, bufnr)
  require "lsp_signature".on_attach({
    bind = true,
    handler_opts = {
      border = "rounded"
    }
  }, bufnr)

  vim.lsp.set_log_level("DEBUG")
  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

  -- Enable completion triggered by <c-x><c-o>
  buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')

  -- Mappings.
  local opts = { noremap=true, silent=true }

  -- See `:help vim.lsp.*` for documentation on any of the below functions
  buf_set_keymap('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<CR>', opts)
  buf_set_keymap('n', 'gd', '<cmd>lua vim.lsp.buf.definition()<CR>', opts)
  buf_set_keymap('n', 'K', '<cmd>lua vim.lsp.buf.hover()<CR>', opts)
  buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
  buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
  buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
  buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
  buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
  buf_set_keymap('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
  buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
  buf_set_keymap('n', '<space>ca', '<cmd>lua vim.lsp.buf.code_action()<CR>', opts)
  buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
  buf_set_keymap('n', '<space>e', '<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>', opts)
  buf_set_keymap('n', '[d', '<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>', opts)
  buf_set_keymap('n', ']d', '<cmd>lua vim.lsp.diagnostic.goto_next()<CR>', opts)
  buf_set_keymap('n', '<space>q', '<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>', opts)
  buf_set_keymap('n', '<space>f', '<cmd>lua vim.lsp.buf.format()<CR>', opts)
end

-- Use a loop to conveniently call 'setup' on multiple servers and
-- map buffer local keybindings when the language server attaches
local nvim_lsp = require('lspconfig')
local capabilities = require('cmp_nvim_lsp').default_capabilities()
local shared = {
  capabilities = capabilities,
  on_attach=on_attach,
}

local servers = { 
  gopls = {
    cmd = {"gopls", "--remote", "auto"}
  },
  pyright = {},
  rust_analyzer = {
    settings = {
      ["rust-analyzer"] = {
        assist = {
          importGranularity = "module",
          importPrefix = "by_self",
        },
        cargo = {
          loadOutDirsFromCheck = true
        },
        procMacro = {
          enable = true
        },
      }
    }
  },
  solargraph = {},
  terraformls = {},
  tsserver = {},
  lua_ls = {}
}

for srv, srv_cfg in pairs(servers) do
  cfg = vim.tbl_deep_extend("error", srv_cfg, shared)
  nvim_lsp[srv].setup(cfg)
end

vim.opt.syntax = "ON"
vim.opt.laststatus = 2
vim.opt.shiftwidth = 4
vim.opt.tabstop = 4
vim.opt.softtabstop = 4
vim.opt.autoindent = true
vim.opt.expandtab = true
vim.opt.nu = true
vim.opt.showcmd = true
vim.opt.wildmenu = true
vim.opt.lazyredraw = true
vim.opt.showmatch = true
vim.opt.hlsearch = true

vim.g.editorconfig = false
vim.keymap.set('n', '<leader><space>', ':nohlsearch<CR>')

-- double spaces
vim.api.nvim_create_autocmd({"FileType"}, {
  desc = "Some files are just double spaced",
  pattern = {"terraform", "css", "html.handlebars", "html", "javascript", "json", "yaml", "lua"},
  command = "setlocal shiftwidth=2 tabstop=2 softtabstop=2"
})

vim.api.nvim_create_autocmd({"BufWritePre"}, {
  pattern = {"*.tfvars", "*.tf"},
  command = "lua vim.lsp.buf.format()"
})

-- attempt to autoformat on save
vim.api.nvim_create_autocmd({"BufWritePre"}, {
  pattern = {"go.mod", "go.sum", "*.go"},
  command = "lua vim.lsp.buf.format()"
})

Logs

gopls logs were empty. I can provide the lsp logs, but they're pretty brutal to read.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ToolsThis label describes issues relating to any tools in the x/tools repository.WaitingForInfoIssue is not actionable because of missing required information, which needs to be provided.goplsIssues related to the Go language server, gopls.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions