hrsh7th / nvim-cmp

A completion plugin for neovim coded in Lua.
MIT License
7.99k stars 397 forks source link

Entire module gets removed when auto-completing from ansible LSP #615

Closed smacz42 closed 2 years ago

smacz42 commented 2 years ago

FAQ

Issues

Neovim Version

NVIM v0.5.1

nvim-cmp config

-- nvim-cmp setup
local cmp = require('cmp')

cmp.setup {
  snippet = {
    expand = function(args)
      require('luasnip').lsp_expand(args.body)
    end,
  },
  -- mapping = {
  --   ['<C-p>'] = cmp.mapping.select_prev_item(),
  --   ['<C-n>'] = cmp.mapping.select_next_item(),
  --   ['<C-d>'] = cmp.mapping.scroll_docs(-4),
  --   ['<C-f>'] = cmp.mapping.scroll_docs(4),
  --   ['<C-Space>'] = cmp.mapping.complete(),
  --   ['<C-e>'] = cmp.mapping.close(),
  --   ['<CR>'] = cmp.mapping.confirm {
  --     behavior = cmp.ConfirmBehavior.Replace,
  --     select = true,
  --   },
  -- },
  sources = {
    { name = 'nvim_lsp' },
    { name = 'luasnip' },
    { name = 'buffer',
      option = {
        get_bufnrs = function()
          return vim.api.nvim_list_bufs()
        end
      },
    },
  },
  experimental = {
    ghost_text = true,
  },
}

local capabilities = require('cmp_nvim_lsp').update_capabilities(vim.lsp.protocol.make_client_capabilities())
local lspconfig = require('lspconfig')

lspconfig.cssls.setup {
  capabilities = capabilities,
}

Description

When auto-completing a module with the ansiblels LSP, when a Class is highlighted (CTRL-n) in the popup, the word disappears. Additionally, selecting an entry does nothing, and instead of having just the incomplete word which the auto-complete is based off of, there is nothing left of that word.

Steps to reproduce

This is on any yaml.ansible filetype.

Expected behavior

I would expect the word to be autocompleted, and the word fragment stay there as I look at the options, and have the selected option fill in when selected.

Actual behavior

I just don't know why when I highlight anything that's coming from the LSP, it completely wipes out the text - and it wipes out all of the text in that word, even if it's a FQCN (e.g. `ansible.builtin.set_fact) it gets rid of the whole thing.

Additional context

Logs from the incident:

[DEBUG][2021-12-05 00:43:01] .../lua/vim/lsp.lua:1047   "on_lines bufnr: 1, changedtick: 10, firstline: 23, lastline: 24, new_lastline: 24, old_byte_size: 15, old_utf32_size: 15, old_utf16_size: 15"  { "          set" }       [20/47][DEBUG][2021-12-05 00:43:01] .../vim/lsp/rpc.lua:395    "rpc.send"      {  jsonrpc = "2.0",  method = "textDocument/didChange",  params = {    contentChanges = { {        range = {          end = {            character = 14,            line = 23          },          start = {            character = 13,            line = 23          }        },        rangeLength = 1,        text = ""      } },    textDocument = {      uri = "file:///home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml",      version = 10    }  }}                                                                                                                                          [DEBUG][2021-12-05 00:43:01] .../lua/vim/lsp.lua:1047   "on_lines bufnr: 1, changedtick: 11, firstline: 23, lastline: 24, new_lastline: 24, old_byte_size: 14, old_utf32_size: 14, old_utf16_size: 14"  { "          se" }
[DEBUG][2021-12-05 00:43:01] .../vim/lsp/rpc.lua:395    "rpc.send"      {  jsonrpc = "2.0",  method = "textDocument/didChange",  params = {    contentChanges = { {        range = {          end = {            character = 13,            line = 23          },          start = {            character = 12,            line = 23          }        },        rangeLength = 1,        text = ""      } },    textDocument = {      uri = "file:///home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml",      version = 11    }  }}                                                                                                                                          [DEBUG][2021-12-05 00:43:01] .../lua/vim/lsp.lua:1047   "on_lines bufnr: 1, changedtick: 12, firstline: 23, lastline: 24, new_lastline: 24, old_byte_size: 13, old_utf32_size: 13, old_utf16_size: 13"  { "          s" }                [DEBUG][2021-12-05 00:43:01] .../vim/lsp/rpc.lua:395    "rpc.send"      {  jsonrpc = "2.0",  method = "textDocument/didChange",  params = {    contentChanges = { {        range = {          end = {            character = 12,            line = 23          },          start = {            character = 11,            line = 23          }        },        rangeLength = 1,        text = ""      } },    textDocument = {      uri = "file:///home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml",      version = 12    }  }}                                                                                                                                          
[DEBUG][2021-12-05 00:43:01] .../lua/vim/lsp.lua:1047   "on_lines bufnr: 1, changedtick: 13, firstline: 23, lastline: 24, new_lastline: 24, old_byte_size: 12, old_utf32_size: 12, old_utf16_size: 12"  { "          " }                 [DEBUG][2021-12-05 00:43:01] .../vim/lsp/rpc.lua:395    "rpc.send"      {  jsonrpc = "2.0",  method = "textDocument/didChange",  params = {    contentChanges = { {        range = {          end = {            character = 11,            line = 23          },          start = {            character = 10,            line = 23          }        },        rangeLength = 1,        text = ""      } },    textDocument = {      uri = "file:///home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml",      version = 13    }  }}                                                                                                                                          [DEBUG][2021-12-05 00:43:01] .../lua/vim/lsp.lua:907    "LSP[ansiblels]"        "client.request"        1       "completionItem/resolve"        {  data = {    atEndOfLine = false,    documentUri = "file:///home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml",    inlineCollections = {},    moduleFqcn = "ansible.builtin.set_fact"  },  detail = "ansible.builtin",  filterText = "set_fact ansible.builtin.set_fact",  kind = 7,  label = "set_fact",  sortText = "2_set_fact",  textEdit = {    newText = "",    range = {      end = {        character = 11,        line = 23      },      start = {        character = 10,        line = 23      }    }  }}       <
function 1>     nil                                                                                                                                                                                                                      [DEBUG][2021-12-05 00:43:01] .../vim/lsp/rpc.lua:395    "rpc.send"      {  id = 3,  jsonrpc = "2.0",  method = "completionItem/resolve",  params = {    data = {      atEndOfLine = false,      documentUri = "file:///home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml",      inlineCollections = {},      moduleFqcn = "ansible.builtin.set_fact"    },    detail = "ansible.builtin",    filterText = "set_fact ansible.builtin.set_fact",    kind = 7,    label = "set_fact",    sortText = "2_set_fact",    textEdit = {      newText = "",      range = {        end = {          character = 11,          line = 23        },        start = {          character = 10,          line = 23        }      }    }  }}                                                                                                                                                                                           [DEBUG][2021-12-05 00:43:01] .../vim/lsp/rpc.lua:496    "rpc.receive"   {  jsonrpc = "2.0",  method = "textDocument/publishDiagnostics",  params = {    diagnostics = { {        message = "Command failed: ansible-playbook /home/andrew
cz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml --syntax-check\n[WARNING]: No inventory was parsed, only implicit localhost is available\n[WARNING]: provided hosts list is empty, only localhost is available. Note that\nthe implicit localhost does not match 'all'\nERROR! no module/action detected in task.\n\nThe error appears to be in '/home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml': line 23, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n        - name: New name of tasks\n          ^ here\n",        range = {          end = {            character = 9.007199254741e+15,            line = 22          },          start = {            character = 10,            line = 22          }        },        severity = 1,        source = "Ansible"      }, {        message = "Implicit map keys need to be followed by map values",        range = {          end = {            character = 13,            line = 23          },          start = {            character = 10,            line = 23          }        },        severity = 1,        source = "Ansible [YAML]"      } },    uri = "file:///home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml"  }}                                           [DEBUG][2021-12-05 00:43:01] .../vim/lsp/rpc.lua:496    "rpc.receive"   {  jsonrpc = "2.0",  method = "textDocument/publishDiagnostics",  params = {    diagnostics = { {        message = "Command failed: ansible-playbook /home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml --syntax-check\n[WARNING]: No inventory was parsed, only implicit localhost is available\n[WARNING]: provided hosts list is empty, only localhost is available. Note that\nthe implicit localhost does not match 'all'\nERROR! no module/action detected in task.\n\nThe error appears to be in '/home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml': line 23, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n        - name: New name of tasks\n          ^ here\n",        range = {          end = {  
          character = 9.007199254741e+15,            line = 22          },          start = {            character = 10,            line = 22          }        },        severity = 1,        source = "Ansible"      }, {        messag
e = "Implicit map keys need to be followed by map values",        range = {          end = {            character = 12,            line = 23          },          start = {            character = 10,            line = 23          }        },        severity = 1,        source = "Ansible [YAML]"      } },    uri = "file:///home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml"  }}                                           [DEBUG][2021-12-05 00:43:01] .../vim/lsp/rpc.lua:496    "rpc.receive"   {  jsonrpc = "2.0",  method = "textDocument/publishDiagnostics",  params = {    diagnostics = { {        message = "Command failed: ansible-playbook /home/andrew
cz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml --syntax-check\n[WARNING]: No inventory was parsed, only implicit localhost is available\n[WARNING]: provided hosts list is empty, only localhost is available. Note that\nthe implicit localhost does not match 'all'\nERROR! no module/action detected in task.\n\nThe error appears to be in '/home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml': line 23, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n        - name: New name of tasks\n          ^ here\n",        range = {          end = {            character = 9.007199254741e+15,            line = 22          },          start = {            character = 10,            line = 22          }        },        severity = 1,        source = "Ansible"      }, {        message = "Implicit map keys need to be followed by map values",        range = {          end = {            character = 11,            line = 23          },          start = {            character = 10,            line = 23          }        },        severity = 1,        source = "Ansible [YAML]"      } },    uri = "file:///home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml"  }}
[DEBUG][2021-12-05 00:43:01] .../vim/lsp/rpc.lua:496    "rpc.receive"   {  jsonrpc = "2.0",  method = "textDocument/publishDiagnostics",  params = {    diagnostics = { {        message = "Command failed: ansible-playbook /home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml --syntax-check\n[WARNING]: No inventory was parsed, only implicit localhost is available\n[WARNING]: provided hosts list is empty, only localhost is
 available. Note that\nthe implicit localhost does not match 'all'\nERROR! no module/action detected in task.\n\nThe error appears to be in '/home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage
.yml': line 23, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n        - name: New name of tasks\n          ^ here\n",        range = {          end = {  
          character = 9.007199254741e+15,            line = 22          },          start = {            character = 10,            line = 22          }        },        severity = 1,        source = "Ansible"      } },    uri = "fil
e:///home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml"  }}
[DEBUG][2021-12-05 00:43:01] .../vim/lsp/rpc.lua:496    "rpc.receive"   {  id = 3,  jsonrpc = "2.0",  result = {    data = {      atEndOfLine = false,      documentUri = "file:///home/andrewcz/Projects/ansible-project-ourcompose_mana
gement/playbooks/create_block_storage.yml",      inlineCollections = { "ansible.builtin" },      moduleFqcn = "ansible.builtin.set_fact"    },    detail = "ansible.builtin",    documentation = {      kind = "markdown",      value = "
*Set host variable(s) and fact(s).*\n\n**Description**\n\n- This action allows setting variables associated to the current host.\n- These variables will be available to subsequent plays during an ansible-playbook run via the host the
y were set on.\n- Set `cacheable` to `yes` to save variables across executions using a fact cache. Variables will keep the set_fact precedence for the current run, but will used 'cached fact' precedence for subsequent ones.\n- Per th
e standard Ansible variable precedence rules, other types of variables have a higher priority, so this value may be overridden.\n\n**Notes**\n\n- Because of the nature of tasks, set_fact will produce 'static' values for a variable. U
nlike normal 'lazy' variables, the value gets evaluated and templated on assignment.\n- Some boolean values (yes, no, true, false) will always be converted to boolean type, unless `DEFAULT_JINJA2_NATIVE` is enabled.  This is done so 
the `var=value` booleans, otherwise it would only be able to create strings, but it also prevents using those values to create YAML strings. Using the setting will restrict k=v to strings, but will allow you to specify string or bool
ean in YAML.\n- To create lists/arrays or dictionary/hashes use YAML notation `var: [val1, val2]`.\n- Since 'cacheable' is now a module param, 'cacheable' is no longer a valid fact name.\n- This action does not use a connection and a
lways executes on the controller."    },    filterText = "set_fact ansible.builtin.set_fact",    kind = 7,    label = "set_fact",    sortText = "2_set_fact",    textEdit = {      newText = "set_fact",      range = {        end = {   
       character = 11,          line = 23        },        start = {          character = 10,          line = 23        }      }    }  }}
[DEBUG][2021-12-05 00:43:05] .../lua/vim/lsp.lua:1047   "on_lines bufnr: 1, changedtick: 14, firstline: 23, lastline: 24, new_lastline: 25, old_byte_size: 11, old_utf32_size: 11, old_utf16_size: 11"  { "", "          " }
[DEBUG][2021-12-05 00:43:05] .../vim/lsp/rpc.lua:395    "rpc.send"      {  jsonrpc = "2.0",  method = "textDocument/didChange",  params = {    contentChanges = { {        range = {          end = {            character = 0,          
  line = 24          },          start = {            character = 0,            line = 23          }        },        rangeLength = 11,        text = "\n          \n"      } },    textDocument = {      uri = "file:///home/andrewcz/Pr
ojects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml",      version = 14    }  }}
[DEBUG][2021-12-05 00:43:05] .../vim/lsp/rpc.lua:496    "rpc.receive"   {  jsonrpc = "2.0",  method = "textDocument/publishDiagnostics",  params = {    diagnostics = { {        message = "Command failed: ansible-playbook /home/andrew
cz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml --syntax-check\n[WARNING]: No inventory was parsed, only implicit localhost is available\n[WARNING]: provided hosts list is empty, only localhost is
 available. Note that\nthe implicit localhost does not match 'all'\nERROR! no module/action detected in task.\n\nThe error appears to be in '/home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage
.yml': line 23, column 11, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n        - name: New name of tasks\n          ^ here\n",        range = {          end = {  
          character = 9.007199254741e+15,            line = 22          },          start = {            character = 10,            line = 22          }        },        severity = 1,        source = "Ansible"      } },    uri = "fil
e:///home/andrewcz/Projects/ansible-project-ourcompose_management/playbooks/create_block_storage.yml"  }}
hrsh7th commented 2 years ago

Could you create the minimal reproducible config based on this?

hrsh7th commented 2 years ago

I can't reproduce it with gopls.

Livins1 commented 2 years ago

this might reproduce. press Tab to auto-complete.


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-path'
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/vim-vsnip'
Plug 'neovim/nvim-lspconfig'
Plug 'L3MON4D3/LuaSnip'
Plug 'saadparwaiz1/cmp_luasnip'
call plug#end()
PlugInstall | quit

" Setup global configuration. More on configuration below.
lua << EOF
local cmp = require "cmp"
local luasnip = require 'luasnip'
cmp.setup({
  completion = {completeopt = 'menu,menuone,noinsert'},
  snippet = {
    expand = function(args)
        expand = function(args) require('luasnip').lsp_expand(args.body) end
    end,
  },
  mapping = {
    ['<c-p>'] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }),
    ['<c-n>'] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }),
    ['<Tab>'] = cmp.mapping.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = false }),
  },
  sources = {
        { name = 'nvim_lsp' },
        { name = 'luasnip' },
        {name= 'buffer' }, 
        {name= 'path' },
  },
  experimental = {
    ghost_text = true,
  },
})

cmp.setup.cmdline(':', {
  sources = cmp.config.sources({
    { name = 'path' },
   -- { name = 'cmdline' },
  })
})

EOF

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

require'lspconfig'.gopls.setup {
  capabilities = capabilities,
}
EOF
smacz42 commented 2 years ago

Sorry, I don't know what gopls is, I'm using ansible. Using the minimal config I am unable to successfully get anything to even autocomplete, much less reproduce the issue.

I am including my relevant dotfiles in case you're able to craft a minimal config out of them. nvim.zip

This may be because I'm using williamboman/nvim-lsp-installer to :LspInstall ansiblels to get the language server for ansible.

smacz42 commented 2 years ago

FWIW, <C-n> is what triggers the removal. If I press the down arrow, it stays there.

smacz42 commented 2 years ago

I think I am able to get it to reproduce, but with a couple manual steps:

First, remove the cached plugins and language servers

WARNING THIS WILL DELETE EVERYTHING, MAKE SURE THIS IS WHAT YOU WANT TO DO FIRST

rm -r /tmp/plugged/
rm -r ~/.local/share/nvim/lsp_servers/

Then source the minimal 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-path'
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/vim-vsnip'
Plug 'neovim/nvim-lspconfig'
Plug 'L3MON4D3/LuaSnip'
Plug 'saadparwaiz1/cmp_luasnip'
" Companion plugin for nvim-lspconfig that allows you to seamlessly install LSP servers locally
Plug 'williamboman/nvim-lsp-installer'
call plug#end()
PlugInstall | quit

" Setup global configuration. More on configuration below.
lua << EOF
-- nvim-cmp setup
local cmp = require('cmp')

cmp.setup {
  snippet = {
    expand = function(args)
      require('luasnip').lsp_expand(args.body)
    end,
  },
 mapping = {
  ['<c-p>'] = cmp.mapping.select_prev_item({ behavior = cmp.SelectBehavior.Insert }),
  ['<c-n>'] = cmp.mapping.select_next_item({ behavior = cmp.SelectBehavior.Insert }),
  ['<Tab>'] = cmp.mapping.confirm({ behavior = cmp.ConfirmBehavior.Replace, select = false }),
 },
  -- mapping = {
  --   ['<C-p>'] = cmp.mapping.select_prev_item(),
  --   ['<C-n>'] = cmp.mapping.select_next_item(),
  --   ['<C-d>'] = cmp.mapping.scroll_docs(-4),
  --   ['<C-f>'] = cmp.mapping.scroll_docs(4),
  --   ['<C-Space>'] = cmp.mapping.complete(),
  --   ['<C-e>'] = cmp.mapping.close(),
  --   ['<CR>'] = cmp.mapping.confirm {
  --     behavior = cmp.ConfirmBehavior.Replace,
  --     select = true,
  --   },
  -- },
  sources = {
    { name = 'nvim_lsp' },
    { name = 'luasnip' },
    { name = 'buffer',
      option = {
        get_bufnrs = function()
          return vim.api.nvim_list_bufs()
        end
      },
    },
  },
  experimental = {
    ghost_text = true,
  },
}

local capabilities = require('cmp_nvim_lsp').update_capabilities(vim.lsp.protocol.make_client_capabilities())
local lspconfig = require('lspconfig')

lspconfig.cssls.setup {
  capabilities = capabilities,
}

-- nvim-lspconfig
vim.lsp.set_log_level('debug')

-- nvim-lsp-installer
local lsp_installer = require("nvim-lsp-installer")

local function on_attach(client, bufnr)
    -- Set up buffer-local keymaps (vim.api.nvim_buf_set_keymap()), etc.
end

-- Register a handler that will be called for all installed servers.
-- Alternatively, you may also register handlers on specific server instances instead (see example below).
lsp_installer.on_server_ready(function(server)
    local default_opts = {
        on_attach = on_attach,
    }

    -- Now we'll create a server_opts table where we'll specify our custom LSP server configuration
    local server_opts = {
        -- Provide settings that should only apply to the "eslintls" server
        ["pyright"] = function()
            default_opts.settings = {
                python = {
                    analysis = {
                        extraPath = {'.'},
                    },
                },
            }
        end,
      }

    -- Use the server's custom settings, if they exist, otherwise default to the default options
    local server_options = server_opts[server.name] and server_opts[server.name]() or default_opts
    server:setup(server_options)

end)

-- cmp_luasnip
require("luasnip/loaders/from_vscode").lazy_load() -- You can pass { path = "./my-snippets/"} as well
EOF

Then run :LspInstall ansiblels.

Clone down this repo: https://gitlab.com/compositionalenterprises/ansible-project-ourcompose_management.git

Edit with neovim the playbooks/migrate.yml playbook. Insert what is shown here to create the new line 17:

   15         delete_droplet: "{{ delete_droplet_prompt }}"                                                                                                                                                        
   16                                                                                                                                                                                                              
   17     - name: Dummy name                                                                                                                                                                                       
   18       blockin
   19                                    

After typing blockin, the popup should show blockinfile Class. Press <C-n> to see the completion disappear.

smacz42 commented 2 years ago

Here's a clip demonstrating the issue. Note that the last time I do the selection, I use the arrow key, which works. The first two times were with <C-n>, which blanks out the completion.

2021-12-27 23-46-15.mkv.zip

dmitmel commented 2 years ago

Here is some information I managed to extract from your repro. I've added this mapping for debugging:

    ['<C-d>'] = cmp.mapping(function()
      local selected_entry = cmp.get_selected_entry()
      print('before resolve', vim.inspect(selected_entry.completion_item))
      print('after resolve', vim.inspect(selected_entry.resolved_completion_item))
    end),

And, here is what it prints when I select the blockinfile entry:

before resolve {
  data = {
    atEndOfLine = true,
    documentUri = "file:///home/dmitmel/dotfiles/ansible-project-ourcompose_management/playbooks/migrate.yml",
    inlineCollections = {},
    moduleFqcn = "ansible.builtin.blockinfile"
  },
  detail = "ansible.builtin",
  filterText = "blockinfile ansible.builtin.blockinfile",
  kind = 7,
  label = "blockinfile",
  sortText = "2_blockinfile",
  textEdit = {
    newText = "",
    range = {
      end = {
        character = 7,
        line = 15
      },
      start = {
        character = 6,
        line = 15
      }
    }
  }
}
after resolve {
  data = {
    atEndOfLine = true,
    documentUri = "file:///home/dmitmel/dotfiles/ansible-project-ourcompose_management/playbooks/migrate.yml",
    inlineCollections = { "ansible.builtin" },
    moduleFqcn = "ansible.builtin.blockinfile"
  },
  detail = "ansible.builtin",
  documentation = {
    kind = "markdown",
    value = "*Insert/update/remove a text block surrounded by marker lines*\n\n**Description**\n\n- This module will insert/update/remove a block of multi-line text surrounded by customizable marker lines.\n\n**Notes**\n\n- When using 'with_*' loops be aware that if you do not set a unique mark the block will be overwritten on each iteration.\n- As of Ansible 2.3, the _dest_ option has been changed to _path_ as default, but _dest_ still works as well.\n- Option _follow_ has been removed in Ansible 2.5, because this module modifies the contents of the file so _follow=no_ doesn't make sense.\n- When more then one block should be handled in one file you must change the _marker_ per task."
  },
  filterText = "blockinfile ansible.builtin.blockinfile",
  kind = 7,
  label = "blockinfile",
  sortText = "2_blockinfile",
  textEdit = {
    newText = "blockinfile:",
    range = {
      end = {
        character = 7,
        line = 15
      },
      start = {
        character = 6,
        line = 15
      }
    }
  }
}

Evidently, the issue is that the Language Server first, on the textDocument/completion request, returns a completion item that has an empty text edit, and only on the completionItem/resolve request, returns an actual text edit.

hrsh7th commented 2 years ago

!!! @dmitmel Thank you!!!

Hm... OK. So I have to replace the all occurrence of self.completion_item.textEdit to self:get_completion_item().textEdit...

stasjok commented 2 years ago

Thank you for fixing it. But I have one problem even after the fix. When selecting any item, inserted text gets erased. But only the first time. If I select a next item, then select back the previous item, text is inserted normally.

If I understand correctly, completionItem/resolve is used for every item separately when selecting an item to get documentation and it can be quite expensive. So is it possible to use resolved text and will it hurt performance? Is ansible-ls is the only language server with such empty edits?

https://user-images.githubusercontent.com/1353637/147781937-419a3271-d0ee-4a5a-ac8b-9543bdb7b554.mp4

folliehiyuki commented 2 years ago

For me ansiblels is the only server where this problem occurs.

I'm having the exact problem as @stasjok described, though for some completion items even getting back to them doesn't make them appear.

powerc9000 commented 2 years ago

Same behavior as @FollieHiyuki on different lsp.

folliehiyuki commented 2 years ago

@hrsh7th should we reopen this issue? It doesn't seem to have been fixed completely. Or should I ask the ansible-language-server instead?

hrsh7th commented 2 years ago

I don't know. I think, if your problem is not the same as odin-language-server's problem, we should re-open this. But if these provlem is the same, I don't think this should re-open because it just duplecated issue.

folliehiyuki commented 2 years ago

As pointed above, the issue is that ansiblels sends textEdit with an empty newText entry to the client until it gets resolved (compared to insertText in odin case).

I think it is a different issue since we are talking about 2 different items here, but I could be wrong.

hrsh7th commented 2 years ago

I think empty TextEdit.newText is valid (It's represented as removing text).

folliehiyuki commented 2 years ago

Thinking about it again, it kinda makes sense to me now, as ansiblels usually completes items to be the full-path version, e.g. type pod -> choose podman_container -> containers.podman.podman_container

I should go ask ansiblels devs whether removing the text and then replacing it is the intended behavior. If it is this issue should not be considered a bug.

Thanks for clarifying.

yaegassy commented 2 years ago

I set up nvim-cmp in my environment and tried it, and I think #801 solved the problem.

DEMO (mp4):

https://user-images.githubusercontent.com/188642/154057504-a499773d-6b73-438e-a96f-eeb3ce4cdf6d.mp4

folliehiyuki commented 2 years ago

Thanks for the hard work! Confirmed working on my end as well.