nvim-cmp icon indicating copy to clipboard operation
nvim-cmp copied to clipboard

Using the autocomplete menu removes the completion when using GDScript LSP Server

Open ForAzens opened this issue 2 years ago • 1 comments

FAQ

  • [X] I have checked the FAQ and it didn't resolve my problem.

Announcement

Minimal reproducible full config

if has('vim_starting')
  set encoding=utf-8
endif
scriptencoding utf-8

if &compatible
  set nocompatible
endif

let s:plug_dir = expand('/tmp/plugged/vim-plug')
if !filereadable(s:plug_dir .. '/plug.vim')
  execute printf('!curl -fLo %s/autoload/plug.vim --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim', s:plug_dir)
end

execute 'set runtimepath+=' . s:plug_dir
call plug#begin(s:plug_dir)
Plug 'hrsh7th/nvim-cmp'
Plug 'hrsh7th/cmp-buffer'
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/vim-vsnip'
Plug 'neovim/nvim-lspconfig'
call plug#end()
PlugInstall | quit

" Setup global configuration. More on configuration below.
lua << EOF
local cmp = require "cmp"
cmp.setup {
  snippet = {
    expand = function(args)
      vim.fn["vsnip#anonymous"](args.body)
    end,
  },

  mapping = {
    ['<CR>'] = cmp.mapping.confirm({ select = true }),
    ["<Tab>"] = cmp.mapping(function(fallback)
      if cmp.visible() then
        cmp.select_next_item()
      elseif vim.fn["vsnip#available"](1) == 1 then
        feedkey("<Plug>(vsnip-expand-or-jump)", "")
      elseif has_words_before() then
        cmp.complete()
      else
        fallback() -- The fallback function sends a already mapped key. In this case, it's probably `<Tab>`.
      end
    end, { "i", "s" }),

    ["<S-Tab>"] = cmp.mapping(function()
      if cmp.visible() then
        cmp.select_prev_item()
      elseif vim.fn["vsnip#jumpable"](-1) == 1 then
        feedkey("<Plug>(vsnip-jump-prev)", "")
      end
    end, { "i", "s" }),
  },

  sources = {
    { name = "nvim_lsp" },
    { name = "buffer" },
  },
}
EOF

lua << EOF
local capabilities = require('cmp_nvim_lsp').update_capabilities(vim.lsp.protocol.make_client_capabilities())

require'lspconfig'.gdscript.setup {
  capabilities = capabilities,
  }
EOF

Description

If you press <CR> without navigating through the autocomplete menu with <TAB>, it will autocomplete the first selection without issues: Peek 2022-08-06 23-25

The problem occurs when you navigate through the autocomplete menu and press <CR> when a item is selected: Peek 2022-08-06 23-24

Steps to reproduce

With the minimal config provided earlier:

  1. Download Godot https://godotengine.org/download
  2. Clone the repository with godot example projects https://github.com/godotengine/godot-demo-projects
  3. Open the project godot-demo-projects/2d/bullet_shower in Godot (otherwise the GDScript LSP server will not work).
  4. Open the file godot-demo-projects/2d/bullet_shower/bullets.gd in neovim with the minimal config provided.
  5. Try to autocomplete some constant or variable with and without navigating through the autocomplete menu.

Expected behavior

It should complete the selected item in the autocomplete menu without any issue.

Actual behavior

It does not complete the selected item, only works when you press <CR> without navigating through the menu.

Additional context

I have been digging into this problem before creating this issue, and what I have found is that the LSP server only returns a label without any insert_text in the LSP type completionItem/resolve. Then the neovim lsp client or nvim-cmp creates a CompletionItem where the property insert_text is an empty string.

Then I found that the "problem" was in this line: https://github.com/hrsh7th/nvim-cmp/blob/main/lua/cmp/core.lua#L414

If I replace that line with the next code, it solves the problem but I don't know if it can cause issues with others LSP servers or sources from nvim-cmp.

local insertText = misc.safe(completion_item.insertText)
if misc.empty(insertText) then
  insertText = nil
end
completion_item.textEdit.newText = insertText or completion_item.word or
    completion_item.label

I got through this solution with the LSP Spec:

	/**
	 * The label of this completion item.
	 *
	 * The label property is also by default the text that
	 * is inserted when selecting this completion.
	 *
	 * If label details are provided the label itself should
	 * be an unqualified name of the completion item.
	 */
	label: string;

https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#completionItem

My knowledge about the LSP Protocol and Lua is limited so maybe this is not correct.

ForAzens avatar Aug 06 '22 22:08 ForAzens

Thank you for detailed investigation.

Hm... In my eyes, it's bug of language server side... but I hope to support this case (if it's rational).

Could you put the godot response?

hrsh7th avatar Aug 14 '22 16:08 hrsh7th

Sorry for the long delay,

here is the godot response: [DEBUG][2022-11-08 19:20:52] .../lua/vim/lsp.lua:1388 "LSP[gdscript]" "client.request" 2 "completionItem/resolve" { data = { position = { character = 1, line = 12 }, textDocument = { uri = "file:///home/forazens/Downloads/godot-demo-projects/2d/bullet_shower/bullets.gd" } }, kind = 21, label = "SPEED_MAX"} <function 1> 8 [DEBUG][2022-11-08 19:20:52] .../lua/vim/lsp.lua:1388 "LSP[gdscript]" "client.request" 2 "workspace/executeCommand" { command = "", title = ""} <function 1> 8

ForAzens avatar Nov 08 '22 18:11 ForAzens

Thanks for sharing your findings @ForAzens - I was just trying to figure this out too

maddawik avatar Mar 05 '23 15:03 maddawik

I am sorry to be that person @hrsh7th, just want to follow up on to help move this issue forward (resolving it would help me greatly). Based on the godot response that @ForAzens shared above, do you think there is anything that can be done in nvim-cmp to support this or is this something the godot engine needs to address in their LSP implementation? Since I'm bugging you let me also take the opportunity to sincerely say thank you for nvim-cmp and the work you do on it.

maddawik avatar May 23 '23 15:05 maddawik