Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

latest update to nvim-cmp causes stack overflow crash #12

Closed
PMassicotte opened this issue Oct 22, 2024 · 39 comments
Closed

latest update to nvim-cmp causes stack overflow crash #12

PMassicotte opened this issue Oct 22, 2024 · 39 comments

Comments

@PMassicotte
Copy link

I am getting a stack overflow when I am trying to use completion since the latest update of nvim-cmp (https://github.com/hrsh7th/nvim-cmp/commits/main/).

...e/.local/share/nvim/lazy/nvim-cmp/lua/cmp/utils/misc.lua:177: stack overflow

Peek 2024-10-22 15-30

I am not sure how to debug that. Any ideas?

@jalvesaq
Copy link
Member

I can't replicate it.

@jalvesaq
Copy link
Member

I have this in my ~/.Rprofile:

# Disable completion from the language server
options(languageserver.server_capabilities =
        list(completionProvider = FALSE,
             completionItemResolve = FALSE))

@PMassicotte
Copy link
Author

I have the same. I will investigate.

@PMassicotte
Copy link
Author

PMassicotte commented Oct 23, 2024

I have found that the overflow occurs in misc.lua in nvim-cmp.

---Copy table
---@generic T
---@param tbl T
---@return T
misc.copy = function(tbl)
  if type(tbl) ~= 'table' then
    return tbl
  end

  if islist(tbl) then
    local copy = {}
    for i, value in ipairs(tbl) do
      copy[i] = misc.copy(value)
    end
    return copy
  end

  local copy = {}
  for key, value in pairs(tbl) do
    copy[key] = misc.copy(value)
  end
  return copy
end

This loops infinitely with this table:

:messages                                                                                                                  
{                                                                                                                          
 kind = "markdown",                                                                                                       
 value = 'function graphics::plot\n\n**The Default Scatterplot Function**\n\nDraw a scatter plot with decorations such as 
axes and titles in the active graphics window.\n\n---\n```r\nplot(x, y = NULL, type = "p", xlim = NULL, ylim = NULL, log = 
"", main = NULL, sub = NULL, xlab = NULL, ylab = NULL, ann = par("ann"), axes = TRUE,\n  frame.plot, panel.first = NULL, pa
nel.last = NULL, asp = NA, xgap.axis = NA, ygap.axis = NA, ...)\n```\n'                                                    
}                                                                                                                          
copy                                                                                                                       
<1>{                                                                                                                       
 cls = "(",                                                                                                               
 documentation = {                                                                                                        
   kind = "markdown",                                                                                                     
   value = 'function graphics::plot\n\n**The Default Scatterplot Function**\n\nDraw a scatter plot with decorations such a
s axes and titles in the active graphics window.\n\n---\n```r\nplot(x, y = NULL, type = "p", xlim = NULL, ylim = NULL, log 
= "", main = NULL, sub = NULL, xlab = NULL, ylab = NULL, ann = par("ann"), axes = TRUE,\n  frame.plot, panel.first = NULL, 
panel.last = NULL, asp = NA, xgap.axis = NA, ygap.axis = NA, ...)\n```\n'                                                  
 },                                                                                                                       
 env = "graphics",                                                                                                        
 items = { <table 1> },                                                                                                   
 kind = 3,                                                                                                                
 label = "plot",                                                                                                          
 sortText = "9",                                                                                                          
 textEdit = {                                                                                                             
   newText = "plot",                                                                                                      
   range = {                                                                                                              
     ["end"] = {                                                                                                          
       character = 1,                                                                                                     
       line = 0                                                                                                           
     },                                                                                                                   
     start = {                                                                                                            
       character = 0,                                                                                                     
       line = 0                                                                                                           
     }                                                                                                                    
   }                                                                                                                      
 }                                                                                                                        
}                                                                                                                          
copy                                                                                                                       
{                                                                                                                          
 kind = "markdown",                                                                                                       
 value = 'function graphics::plot\n\n**The Default Scatterplot Function**\n\nDraw a scatter plot with decorations such as 
axes and titles in the active graphics window.\n\n---\n```r\nplot(x, y = NULL, type = "p", xlim = NULL, ylim = NULL, log = 
"", main = NULL, sub = NULL, xlab = NULL, ylab = NULL, ann = par("ann"), axes = TRUE,\n  frame.plot, panel.first = NULL, pa
nel.last = NULL, asp = NA, xgap.axis = NA, ygap.axis = NA, ...)\n```\n'                                                    
}                                                                                                                          
copy                                                                                                                       
<1>{                                                                                                                       
 cls = "(",                                                                                                               
 documentation = {                                                                                                        
   kind = "markdown",                                                                                                     
   value = 'function graphics::plot\n\n**The Default Scatterplot Function**\n\nDraw a scatter plot with decorations such a
s axes and titles in the active graphics window.\n\n---\n```r\nplot(x, y = NULL, type = "p", xlim = NULL, ylim = NULL, log 
= "", main = NULL, sub = NULL, xlab = NULL, ylab = NULL, ann = par("ann"), axes = TRUE,\n  frame.plot, panel.first = NULL, 
panel.last = NULL, asp = NA, xgap.axis = NA, ygap.axis = NA, ...)\n```\n'                                                  
 },  

I am not sure what is going on. All other lsp (python, etc.) still work fine.

@PMassicotte
Copy link
Author

More investigation.

At some point nvim-cmp receive this from cmp_r

Vim(lua):E5108: Error executing lua .../filoche/.local/share/nvim/lazy/cmp-r/lua/cmp_r/init.lua:552: bad argument #1 to 'gs
ub' (string expected, got nil)                                                                                             
stack traceback:                                                                                                           
^I[C]: in function 'gsub'                                                                                                  
^I.../filoche/.local/share/nvim/lazy/cmp-r/lua/cmp_r/init.lua:552: in function 'complete_cb'                               
^I[string ":lua"]:1: in main chunk                                                                                         
^I[C]: in function 'execute'                                                                                               
^I/home/filoche/.local/share/nvim/lazy/R.nvim/lua/r/job.lua:48: in function 'exec_stdout_cmd'                              
^I/home/filoche/.local/share/nvim/lazy/R.nvim/lua/r/job.lua:69: in function </home/filoche/.local/share/nvim/lazy/R.nvim/lu
a/r/job.lua:58>                                                                                                            
stack traceback:                                                                                                           
^I[C]: in function 'execute'                                                                                               
^I/home/filoche/.local/share/nvim/lazy/R.nvim/lua/r/job.lua:48: in function 'exec_stdout_cmd'                              
^I/home/filoche/.local/share/nvim/lazy/R.nvim/lua/r/job.lua:69: in function </home/filoche/.local/share/nvim/lazy/R.nvim/lu
a/r/job.lua:58>                                                                                                                                                                                                                            

@PMassicotte
Copy link
Author

PMassicotte commented Oct 23, 2024

I found the problematic commit:

hrsh7th/nvim-cmp@1a1d7ec

using this fixes the issue for now

    "hrsh7th/nvim-cmp",
    commit = "ae644feb7b67bf1ce4260c231d1d4300b19c6f30",

@jalvesaq
Copy link
Member

plot appears twice in the completion list (one as a function of base and the other as part of graphics). Looking at problematic commit, the only thing that looks strange to me is lines 74-76 of lua/cmp/entry.lua:

    for k, v in pairs(completion_item) do
      self.completion_item[k] = v or self.completion_item[k]
    end

I have no familiarity with nvim-cmp code, but it seems that if v is nil, an old item will be used.

Anyway, I can't replicate the bug on my side.

@jalvesaq
Copy link
Member

I fixed two bugs in the C code in the last commit.

After starting R and opening the Object Browser, the bugs could be replicated with the following code:

ddd <- data.frame(aa = 1, bb = 2)
rm(ddd)
x <- 1

Bug 1: The Object Browser wasn't updated after rm(ddd).

Bug 2: Invalid string received by lua/r/browser.lua after x <- 1.

Maybe the second bug was causing the stack overflow crash in cmp...

@PMassicotte
Copy link
Author

ah nice, i am actively trying to debug this for the past hour. Have you created a branch?

@PMassicotte
Copy link
Author

PMassicotte commented Oct 28, 2024

No luck, still having this when I hit enter on a completion selection

...e/.local/share/nvim/lazy/nvim-cmp/lua/cmp/utils/misc.lua:177: stack overflow    

I am trying to make a reproducible example with this

https://github.com/hrsh7th/nvim-cmp/blob/main/utils/vimrc.vim

@PMassicotte
Copy link
Author

PMassicotte commented Oct 28, 2024

I am able to reproduce with this vimrc.vim

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)
endif

execute 'set runtimepath+=' . s:plug_dir
call plug#begin(s:plug_dir)

" Plugin list
Plug 'hrsh7th/nvim-cmp'
Plug 'hrsh7th/cmp-buffer'
Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/vim-vsnip'
Plug 'neovim/nvim-lspconfig'
Plug 'R-nvim/cmp-r'
Plug 'R-nvim/R.nvim'
Plug 'nvim-treesitter/nvim-treesitter', {'do': ':TSUpdate'}

call plug#end()
PlugInstall | quit

" Setup nvim-cmp
lua << EOF
local cmp = require("cmp")
cmp.setup {
  snippet = {
    expand = function(args)
      vim.fn["vsnip#anonymous"](args.body)
    end,
  },
  mapping = cmp.mapping.preset.insert({
   ["<C-n>"] = cmp.mapping.select_next_item(),
                    ["<C-p>"] = cmp.mapping.select_prev_item(),
                    ["<C-d>"] = cmp.mapping.scroll_docs(-4),
                    ["<C-f>"] = cmp.mapping.scroll_docs(4),
                    ["<C-Space>"] = cmp.mapping.complete({}),
                    ["<CR>"] = cmp.mapping.confirm({
                        behavior = cmp.ConfirmBehavior.insert,
                        select = false,
                    }),
                    ["<Tab>"] = cmp.mapping(function(fallback)
                        if cmp.visible() then
                            cmp.select_next_item()
                        -- elseif luasnip.expand_or_locally_jumpable() then
                        --     luasnip.expand_or_jump()
                        else
                            fallback()
                        end
                    end, { "i", "s" }),
                    ["<S-Tab>"] = cmp.mapping(function(fallback)
                        if cmp.visible() then
                            cmp.select_prev_item()
                        -- elseif luasnip.locally_jumpable(-1) then
                        --     luasnip.jump(-1)
                        else
                            fallback()
                        end
                    end, { "i", "s" }),
  }),
  sources = cmp.config.sources({
    { name = "nvim_lsp" },
    { name = "buffer" },
    { name = "cmp_r" },
  })
}

-- Configure cmp-r
require("cmp_r").setup({})
-- require("R.nvim").setup({})

-- Set up LSP with cmp capabilities
local capabilities = require('cmp_nvim_lsp').default_capabilities()

EOF

" Setup Treesitter
lua << EOF
require'nvim-treesitter.configs'.setup {
 ensure_installed = { "markdown", "markdown_inline", "r", "rnoweb", "yaml", "vim"},
  highlight = {
    enable = true, -- Enable syntax highlighting
  },
}
EOF

Then open a file like this

nvim -u ./vimrc.vim test.R

@jalvesaq
Copy link
Member

Still no bug on my side with your vimrc.vim. Does it make any difference to delete the R.nvim cache?

cd ~/.cache
rm -rf R.nvim

@PMassicotte
Copy link
Author

No luck either. With my minimal example, do you get any completion at all? And no crash?

@jalvesaq
Copy link
Member

Yes, the completion works normally, and there is no crash.

@PMassicotte
Copy link
Author

PMassicotte commented Oct 28, 2024

Very strange. This is starting nvim with nothing else. Maybe my nvim version? I will explore this.

@PMassicotte
Copy link
Author

I tried both stable and nightly and same issue.

@jalvesaq
Copy link
Member

A similar bug was already reported, but not reproducible hrsh7th/nvim-cmp#1347

@PMassicotte
Copy link
Author

I am updating lua, just in case, I am out of ideas.

@jalvesaq
Copy link
Member

As far as I know, bugs such "stack overflow" or "buffer overflow" should only happen in languages with low-level access to memory management, such as C or C++. Other programming languages (Java, R, Python, Lua, etc...) protect their users from these bugs (they don't give users the power to create them).

Can you replicate the bug on a different machine?

@PMassicotte
Copy link
Author

Can you replicate the bug on a different machine?

Yes. Both on at home and at job. Both on linux.

@PMassicotte
Copy link
Author

As far as I know, bugs such "stack overflow" or "buffer overflow" should only happen in languages with low-level access to memory management, such as C or C++. Other programming languages (Java, R, Python, Lua, etc...) protect their users from these bugs (they don't give users the power to create them).

Makes sense.

The issue is that the table received here #12 (comment) seems to contain indefinite number of entries and the copy function eventually crashes.

@PMassicotte
Copy link
Author

More info.

The error originate from the call to copy here:

https://github.com/hrsh7th/nvim-cmp/blob/29fb4854573355792df9e156cb779f0d31308796/lua/cmp/core.lua#L436

  local completion_item = misc.copy(e.completion_item)

If I add a print statement

print("confirm", vim.inspect(e.completion_item))
local completion_item = misc.copy(e.completion_item)

I am getting this output (when I select lm from the completion menu).

{                                                                                                               
 cls = "(",                                                                                                               
 documentation = {                                                                                                        
   kind = "markdown",                                                                                                     
   value = 'function stats::lm\n\n**Fitting Linear Models**\n\n`lm` is used to fit linear models, including multivariate o
nes. It can be used to carry out regression, single stratum analysis of variance and\nanalysis of covariance (although `aov
` may provide a more convenient interface for these).\n\n---\n```r\nlm(formula, data, subset, weights, na.action, method = 
"qr", model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, contrasts = NULL,\n  offset, ...)\n```\n'         
 },                                                                                                                       
 env = "stats",                                                                                                           
 items = { <table 1> },                                                                                                   
 kind = 3,                                                                                                                
 label = "lm",                                                                                                            
 sortText = "9",                                                                                                          
 textEdit = {                                                                                                             
   newText = "lm",                                                                                                        
   range = {                                                                                                              
     ["end"] = {                                                                                                          
       character = 1,                                                                                                     
       line = 0                                                                                                           
     },                                                                                                                   
     start = {                                                                                                            
       character = 0,                                                                                                     
       line = 0                                                                                                           
     }                                                                                                                    
   }                                                                                                                      
 }                                                                                                                        
} 

This seems ok, the received table is only of length 1.

Now in https://github.com/hrsh7th/nvim-cmp/blob/29fb4854573355792df9e156cb779f0d31308796/lua/cmp/utils/misc.lua#L169,

misc.copy = function(tbl)
    if type(tbl) ~= "table" then
        return tbl
    end

    if islist(tbl) then
        local copy = {}
        -- print the length of the table
        print("Reveived table in misc.copy\n" .. vim.inspect(tbl))
        for i, value in ipairs(tbl) do
            copy[i] = misc.copy(value)
        end
        return copy
    end

    local copy = {}
    for key, value in pairs(tbl) do
        copy[key] = misc.copy(value)
    end
    return copy
end

If I print the content of the reveived tbl I have this that repeats indfinetly.

Reveived table in misc.copy                                                                                                
<1>{ {                                                                                                                     
    cls = "(",                                                                                                             
    documentation = {                                                                                                      
      kind = "markdown",                                                                                                   
      value = 'function stats::lm\n\n**Fitting Linear Models**\n\n`lm` is used to fit linear models, including multivariate
 ones. It can be used to carry out regression, single stratum analysis of variance and\nanalysis of covariance (although `a
ov` may provide a more convenient interface for these).\n\n---\n```r\nlm(formula, data, subset, weights, na.action, method 
= "qr", model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, contrasts = NULL,\n  offset, ...)\n```\n'       
    },                                                                                                                     
    env = "stats",                                                                                                         
    items = <table 1>,                                                                                                     
    kind = 3,                                                                                                              
    label = "lm",                                                                                                          
    sortText = "9",                                                                                                        
    textEdit = {                                                                                                           
      newText = "lm",                                                                                                      
      range = {                                                                                                            
        ["end"] = {                                                                                                        
          character = 2,                                                                                                   
          line = 0                                                                                                         
        },                                                                                                                 
        start = {                                                                                                          
          character = 0,                                                                                                   
          line = 0                                                                                                         
        }                                                                                                                  
      }                                                                                                                    
    }                                                                                                                      
  } }                                                                                                                      
Reveived table in misc.copy                                                                                                
<1>{ {                                                                                                                     
    cls = "(",                                                                                                             
    documentation = {                                                                                                      
      kind = "markdown",                                                                                                   
      value = 'function stats::lm\n\n**Fitting Linear Models**\n\n`lm` is used to fit linear models, including multivariate
 ones. It can be used to carry out regression, single stratum analysis of variance and\nanalysis of covariance (although `a
ov` may provide a more convenient interface for these).\n\n---\n```r\nlm(formula, data, subset, weights, na.action, method 
= "qr", model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, contrasts = NULL,\n  offset, ...)\n```\n'       
    },                                                                                                                     
    env = "stats",                                                                                                         
    items = <table 1>,                                                                                                     
    kind = 3,                                                                                                              
    label = "lm",                                                                                                          
    sortText = "9",                                                                                                        
    textEdit = {                                                                                                           
      newText = "lm",                                                                                                      
      range = {                                                                                                            
        ["end"] = {                                                                                                        
          character = 2,                                                                                                   
          line = 0                                                                                                         
        },                                                                                                                 
        start = {                                                                                                          
          character = 0,                                                                                                   
          line = 0  
          ....
          ...
          ...

@jalvesaq
Copy link
Member

I can't imagine the infinite loop coming from the rnvimserver because it would exhaust the RAM and crash before sending the string to cmp. So, I think somehow cmp itself is creating the infinite loop. Could you try different cmp sort methods? I'm using this:

                sorting = {
                    comparators = {
                        cmp.config.compare.order,
                    },
                },

@PMassicotte
Copy link
Author

PMassicotte commented Oct 28, 2024

I replaced my config with yours and still the same (but now the order is different).

Added 2 print statements here and I never receive the "Done copy" message.

    feedkeys.call("", "n", function()
        local ctx = context.new()
        print("confirm", vim.inspect(e.completion_item))
        local completion_item = misc.copy(e.completion_item)
        print("Done copy")
        if not completion_item.textEdit then
            completion_item.textEdit = {}
            local insertText = completion_item.insertText
            if misc.empty(insertText) then
                insertText = nil
            end
            completion_item.textEdit.newText = insertText or completion_item.word or completion_item.label
        end
        local behavior = option.behavior or config.get().confirmation.default_behavior
        if behavior == types.cmp.ConfirmBehavior.Replace then
            completion_item.textEdit.range = e.replace_range
        else
            completion_item.textEdit.range = e.insert_range
        end

        local diff_before = math.max(0, e.context.cursor.col - (completion_item.textEdit.range.start.character + 1))
        local diff_after = math.max(0, (completion_item.textEdit.range["end"].character + 1) - e.context.cursor.col)
        local new_text = completion_item.textEdit.newText
        completion_item.textEdit.range.start.line = ctx.cursor.line
        completion_item.textEdit.range.start.character = (ctx.cursor.col - 1) - diff_before
        completion_item.textEdit.range["end"].line = ctx.cursor.line
        completion_item.textEdit.range["end"].character = (ctx.cursor.col - 1) + diff_after
        if api.is_insert_mode() then
            if false then
                --To use complex expansion debug.
                vim.print({ -- luacheck: ignore
                    item = e.completion_item,
                    diff_before = diff_before,
                    diff_after = diff_after,
                    new_text = new_text,
                    text_edit_new_text = completion_item.textEdit.newText,
                    range_start = completion_item.textEdit.range.start.character,
                    range_end = completion_item.textEdit.range["end"].character,
                    original_range_start = e.completion_item.textEdit.range.start.character,
                    original_range_end = e.completion_item.textEdit.range["end"].character,
                    cursor_line = ctx.cursor_line,
                    cursor_col0 = ctx.cursor.col - 1,
                })
            end
            local is_snippet = completion_item.insertTextFormat == types.lsp.InsertTextFormat.Snippet
            if is_snippet then
                completion_item.textEdit.newText = ""
            end
            vim.lsp.util.apply_text_edits({ completion_item.textEdit }, ctx.bufnr, "utf-8")

            local texts = vim.split(completion_item.textEdit.newText, "\n")
            vim.api.nvim_win_set_cursor(0, {
                completion_item.textEdit.range.start.line + #texts,
                (#texts == 1 and (completion_item.textEdit.range.start.character + #texts[1]) or #texts[#texts]),
            })
            if is_snippet then
                config.get().snippet.expand({
                    body = new_text,
                    insert_text_mode = completion_item.insertTextMode,
                })
            end
        else
            local keys = {}
            table.insert(
                keys,
                keymap.backspace(
                    ctx.cursor_line:sub(completion_item.textEdit.range.start.character + 1, ctx.cursor.col - 1)
                )
            )
            table.insert(
                keys,
                keymap.delete(ctx.cursor_line:sub(ctx.cursor.col, completion_item.textEdit.range["end"].character))
            )
            table.insert(keys, new_text)
            feedkeys.call(table.concat(keys, ""), "in")
        end
    end)

Ccing @yioneko and @hrsh7th just in case they have some ideas.

@jalvesaq
Copy link
Member

Maybe this was caused by the bug fixed in the last R.nvim commit...

@PMassicotte
Copy link
Author

No luck. Maybe I can close this if it is only me with this issue.

@PMassicotte
Copy link
Author

I have added that to my init.lua

vim.cmd("set verbosefile=~/.config/nvim/nvimlog")
vim.cmd("set verbose=3")

I am getting this information on crash:

continuing in nvim_exec2() called at LspAttach Autocommands for "*":0-- INSERT --

 -- INSERT --
not found in runtime path: "ftplugin/cmp_menu[.]{vim,lua} ftplugin/cmp_menu_*.{vim,lua} ftplugin/cmp_menu/*.{vim,lua}"
not found in runtime path: "indent/cmp_menu[.]{vim,lua}"
not found in runtime path: "parser/cmp_menu.*"-- INSERT --









-- INSERT --
not found in runtime path: "ftplugin/cmp_docs[.]{vim,lua} ftplugin/cmp_docs_*.{vim,lua} ftplugin/cmp_docs/*.{vim,lua}"
not found in runtime path: "indent/cmp_docs[.]{vim,lua}"
not found in runtime path: "parser/cmp_docs.*"
line 0: sourcing "/home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/lsp_markdown.vim"
line 8: sourcing "/home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/markdown.vim"
line 21: sourcing "/home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/html.vim"
line 23: sourcing "/home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/xml.vim"
line 301: sourcing "/home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/dtd.vim"
finished sourcing /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/dtd.vim
continuing in /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/xml.vim
finished sourcing /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/xml.vim
continuing in /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/html.vim
line 273: sourcing "/home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/javascript.vim"
finished sourcing /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/javascript.vim
continuing in /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/html.vim
line 298: sourcing "/home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/vb.vim"
finished sourcing /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/vb.vim
continuing in /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/html.vim
line 308: sourcing "/home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/css.vim"
finished sourcing /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/css.vim
continuing in /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/html.vim
finished sourcing /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/html.vim
continuing in /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/markdown.vim
line 142: sourcing "/home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/yaml.vim"
finished sourcing /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/yaml.vim
continuing in /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/markdown.vim
finished sourcing /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/markdown.vim
continuing in /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/lsp_markdown.vim
finished sourcing /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/lsp_markdown.vim
continuing in nvim_exec2()
line 0: sourcing "/home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/r.vim"
finished sourcing /home/filoche/.local/share/bob/v0.10.2/share/nvim/runtime/syntax/r.vim
continuing in nvim_exec2()-- INSERT --

















vim/shared.lua:0: stack overflow-- INSERT --

@jalvesaq
Copy link
Member

We can't the issue before it's fixed.
Did you try using the minimal configuration from the Wiki?

@PMassicotte
Copy link
Author

We can't the issue before it's fixed. Did you try using the minimal configuration from the Wiki?

Not yet. I made my own for eventually open an issue on nvim-cmp. I will try it and see if I have the same issue.

@PMassicotte
Copy link
Author

Same issue with the minimal config.

Peek 2024-10-30 09-23

@emeralit
Copy link

@PMassicotte you are not alone. I have the same bug and I use your workaround for now.

@jalvesaq
Copy link
Member

You can try making these changes:

diff --git a/lua/cmp_r/init.lua b/lua/cmp_r/init.lua
index 9670b90..8b8a770 100644
--- a/lua/cmp_r/init.lua
+++ b/lua/cmp_r/init.lua
@@ -531,6 +531,7 @@ end
 ---the data to rnvimserver which calls back this function.
 ---@param txt string The text almost ready to be displayed.
 source.resolve_cb = function(txt)
+    vim.fn.writefile({ "", vim.inspect(txt) }, "/tmp/cmp_r_resolve_log", "a")
     local s = fix_doc(txt)
     if last_compl_item.def then
         s = last_compl_item.label .. fix_doc(last_compl_item.def) .. "\n---\n" .. s
@@ -546,6 +547,7 @@ end
 ---@param compl table The completion data.
 source.complete_cb = function(cid, compl)
     if cid ~= compl_id then return nil end
+    vim.fn.writefile({ "", vim.inspect(compl) }, "/tmp/cmp_r_complete_log", "a")
 
     local resp = {}
     for _, v in pairs(compl) do

Then, look at the log files and try to find something strange. To follow the log files as more lines are appended:

tail -f /tmp/cmp_r_resolve_log

@PMassicotte
Copy link
Author

When I try to complete with selecting lm()

cmp_r_complete_log.txt
cmp_r_resolve_log.txt

@jalvesaq
Copy link
Member

After replacing \@ with \r and formatting, cmp_r_complete_log.txt becomes:

{
    { cls = "(", env = "nvimcom", label = "etags2ctags" },
    { cls = "(", env = "nvimcom", label = "nvim.interlace.rmd" },
    { cls = "(", env = "nvimcom", label = "nvim.interlace.rnoweb" },
   --- 2552 lines omitted
    { cls = "(", env = "base", label = "xtfrm.POSIXlt" },
    { cls = "(", env = "base", label = "xzfile" },
    { cls = "(", env = "base", label = "zapsmall" }
}

No visible problem.

After replacing \20 with \r and formatting, cmp_r_resolve_log.txt becomes the following text wrapped by single quotes:

function stats::lm

**Fitting Linear Models**

`lm` is used to fit linear models, including multivariate ones. It can be used to carry out regression, single stratum analysis of variance and
analysis of covariance (although `aov` may provide a more convenient interface for these).

---
```r
lm(formula, data, subset, weights, na.action, method = "qr", model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE, contrasts = NULL,
  offset, ...)
```

It's just a valid Markdown text. The --- line is replaced with a horizontal line by nvim-cmp.

@jalvesaq
Copy link
Member

jalvesaq commented Nov 1, 2024

In the Lua table from cmp_r_complete_log.txt, the following labels are repeated:

  • body<-: from methods and base.
  • kronecker: from methodsandbase`.
  • plot: from graphics and base.
  • vi: from nvimcom and utils.

My guess is that nvim-cmp is failing in some systems (perhaps depending on the Lua engine installed) when there are repeated labels, and the reason would be what I said on #12 (comment)

In the past, BSD users have fixed bugs in the C code of nvimcom that only affected them because BSD has a somewhat more secure system, and it seems that macOS inherits some BSD features. So, perhaps some Lua engines are less tolerant of repeated labels than others.

But if repeated labels were the problem, there should be no stack overflow when completing lm because there is no repeated label beginning with the letter "L".

Conclusion: "I know that I know nothing".

@PMassicotte
Copy link
Author

That seems to be a not so easy issue to fix. Thank you for looking at it. I will continue to investigate and report back if I find a solution.

@hrsh7th
Copy link

hrsh7th commented Nov 2, 2024

IMO, this issue should be fixed with this.

hrsh7th/nvim-cmp#2076

@emeralit
Copy link

emeralit commented Nov 2, 2024

Thanks you @hrsh7th. The last commit solved the issue.

@PMassicotte
Copy link
Author

PMassicotte commented Nov 2, 2024

IMO, this issue should be fixed with this.

hrsh7th/nvim-cmp#2076

Thank you very much @hrsh7th , this solved it. Thank for the great plugin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants