ycm-core / YouCompleteMe

A code-completion engine for Vim
http://ycm-core.github.io/YouCompleteMe/
GNU General Public License v3.0
25.36k stars 2.8k forks source link

YCM error when g:ycm_show_detailed_diag_in_popup = 1 #4196

Closed Aster89 closed 5 months ago

Aster89 commented 8 months ago

Issue Prelude

Please complete these steps and check these boxes (by putting an x inside the brackets) before filing your issue:

Thank you for adhering to this process! It ensures your issue is resolved quickly and that neither your nor our time is needlessly wasted.

Issue Details

Provide a clear description of the problem, including the following key questions:

Include steps to reproduce here.

  1. vim -Nu /path/to/YCM/ycm_vimrc_minimal
  2. type the code
    int main () {
    const int &&
        rd = 1;
    rd = 4;
    }
  3. run let g:ycm_show_detailed_diag_in_popup = 1
  4. move to line 2
  5. hit \d

Include description of a minimal test case, including any actual code required to reproduce the issue.

No changes to vimrc_ycm_minimal.

The C++ error shown in the popup.

Include description of the expected behaviour.

A YCM error

Error detected while processing function <SNR>37_ShowDetailedDiagnostic:
line    3:
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/enrico/.vim/plugged/YouCompleteMe/python/ycm/youcompleteme.py", line 863, in ShowDetailedDiagnostic
    prop = vimsupport.GetTextPropertyForDiag( buffer_number,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/enrico/.vim/plugged/YouCompleteMe/python/ycm/vimsupport.py", line 296, in GetTextPropertyForDiag
    return next( filter(
           ^^^^^^^^^^^^^
StopIteration

Diagnostic data

Output of vim --version

VIM - Vi IMproved 9.0 (2022 Jun 28, compiled Oct 11 2023 19:17:46)
Included patches: 1-2010
Compiled by Arch Linux
Huge version with GTK3 GUI.  Features included (+) or not (-):
+acl               +cindent           +cursorshape       +file_in_path      +job               +menu              +mouse_urxvt       +popupwin          +signs             -tag_any_white     +user_commands     +windows
+arabic            +clientserver      +dialog_con_gui    +find_in_path      +jumplist          +mksession         +mouse_xterm       +postscript        +smartindent       +tcl/dyn           +vartabs           +writebackup
+autocmd           +clipboard         +diff              +float             +keymap            +modify_fname      +multi_byte        +printer           -sodium            +termguicolors     +vertsplit         +X11
+autochdir         +cmdline_compl     +digraphs          +folding           +lambda            +mouse             +multi_lang        +profile           +sound             +terminal          +vim9script        +xattr
-autoservername    +cmdline_hist      +dnd               -footer            +langmap           +mouseshape        -mzscheme          -python            +spell             +terminfo          +viminfo           -xfontset
+balloon_eval      +cmdline_info      -ebcdic            +fork()            +libcall           +mouse_dec         +netbeans_intg     +python3/dyn       +startuptime       +termresponse      +virtualedit       +xim
+balloon_eval_term +comments          +emacs_tags        +gettext           +linebreak         +mouse_gpm         +num64             +quickfix          +statusline        +textobjects       +visual            -xpm
+browse            +conceal           +eval              -hangul_input      +lispindent        -mouse_jsbterm     +packages          +reltime           -sun_workshop      +textprop          +visualextra       +xsmp_interact
++builtin_terms    +cryptv            +ex_extra          +iconv             +listcmds          +mouse_netterm     +path_extra        +rightleft         +syntax            +timers            +vreplace          +xterm_clipboard
+byte_offset       +cscope            +extra_search      +insert_expand     +localmap          +mouse_sgr         +perl/dyn          +ruby/dyn          +tag_binary        +title             +wildignore        -xterm_save
+channel           +cursorbind        -farsi             +ipv6              +lua/dyn           -mouse_sysmouse    +persistent_undo   +scrollbind        -tag_old_static    +toolbar           +wildmenu
   system vimrc file: "/etc/vimrc"
     user vimrc file: "$HOME/.vimrc"
 2nd user vimrc file: "~/.vim/vimrc"
      user exrc file: "$HOME/.exrc"
  system gvimrc file: "/etc/gvimrc"
    user gvimrc file: "$HOME/.gvimrc"
2nd user gvimrc file: "~/.vim/gvimrc"
       defaults file: "$VIMRUNTIME/defaults.vim"
    system menu file: "$VIMRUNTIME/menu.vim"
  fall-back for $VIM: "/usr/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -DFEAT_GUI_GTK -I/usr/include/gtk-3.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/sysprof-6 -I/usr/include/harfbuzz -I/usr/include/freetype2 -I/usr/include/lib
png16 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/gio-unix-2.0 -I/usr/include/cloudproviders -I/usr/include/atk-1.0 -I/usr/include/at-spi2-at
k/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0 -I/usr/lib/dbus-1.0/include -pthread -march=x86-64 -mtune=generic -O2 -pipe -fno-plt -fexceptions -Wformat -Werror=format-security -fstack-clash-protection -fcf-protection -g -ffile-prefix-map=/build
/vim/src=/usr/src/debug/vim -flto=auto -D_REENTRANT -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
Linking: gcc -Wl,-E -Wl,-rpath,/usr/lib/perl5/5.38/core_perl/CORE -Wl,-O1,--sort-common,--as-needed,-z,relro,-z,now -flto=auto -L/usr/local/lib -o vim -lgtk-3 -lgdk-3 -lz -lpangocairo-1.0 -lpango-1.0 -lharfbuzz -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixb
uf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lSM -lICE -lXt -lX11 -lXdmcp -lSM -lICE -lm -ltinfo -lelf -lcanberra -lacl -lattr -lgpm -L/usr/lib -ltclstub8.6 -ldl -lz -lpthread -lm

Output of YcmDebugInfo

Printing YouCompleteMe debug information...
-- Resolve completions: Up front
-- Client logfile: /tmp/ycm_z74pldnl.log
-- Server Python interpreter: /usr/bin/python3
-- Server Python version: 3.11.5
-- Server has Clang support compiled in: True
-- Clang version: clang version 16.0.1 (https://github.com/ycm-core/llvm f6d8fd76462bf638dd3368ddb7f60a23f82e8bad)
-- Extra configuration file found and loaded
-- Extra configuration path: /home/enrico/.ycm_extra_conf.py
-- C-family completer debug information:
--   Clangd running
--   Clangd process ID: 1258332
--   Clangd executable: ['/home/enrico/.vim/plugged/YouCompleteMe/third_party/ycmd/third_party/clangd/output/bin/clangd', '-header-insertion-decorators=0', '-resource-dir=/home/enrico/.vim/plugged/YouCompleteMe/third_party/ycmd/third_party/clang/lib/clang
/17.0.1', '-limit-results=500', '-log=verbose']
--   Clangd logfiles:
--     /tmp/clangd_stderr44x3stef.log
--   Clangd Server State: Initialized
--   Clangd Project Directory: /home/enrico
--   Clangd Settings: {}
--   Clangd Compilation Command: ['clang-tool', '-x', 'c++', '-std=c++20', '-Wall', '-Wextra', '-Wattributes', '/home/enrico/ycm.cpp']
-- Server running at: http://127.0.0.1:55717
-- Server process ID: 1258305
-- Server logfiles:
--   /tmp/ycmd_55717_stdout_ffqd9cx_.log
--   /tmp/ycmd_55717_stderr_f8evwdnv.log
-- Semantic highlighting supported: True
-- Virtual text supported: True
-- Popup windows supported: True

Output of YcmDiags

ycm.cpp|4 col 8 error| Cannot assign to variable 'rd' with const-qualified type 'const int &&' ycm.cpp:2:5: note: variable 'rd' declared const here [typecheck_assign_const]
ycm.cpp|2 col 5 info| Variable 'rd' declared const here ycm.cpp:4:8: error: cannot assign to variable 'rd' with const-qualified type 'const int &&'

Output of git rev-parse HEAD in YouCompleteMe installation directory

cc9a3ae3efdcc7d038aab0620ea28882533c236c

Contents of YCM, ycmd and completion engine logfiles

Reproduce the issue with vim -Nu /path/to/YCM/vimrc_ycm_minimal, which enabled debug logging and other useful diagnostics. Include a link to a gist containing all of the log files listed by :YcmToggleLogs.

OS version, distribution, etc.

Up-to-date ArchLinux

Output of build/install commands

No install problem

puremourning commented 8 months ago

What happens?

Aster89 commented 8 months ago

I missed quite an important info! Updated.

bstaletic commented 8 months ago

@Aster89 Itl think your html formatting got a little screwed. What is the 5th step exactly?

Aster89 commented 8 months ago

@bstaletic , yep, <kbd>\<kbd> instead of <kbd>\\<kbd> is the culprit. Corrected now.

Aster89 commented 8 months ago

I've hit this again with an Haskell file. Specifically, the following erronous (for whatever reason, ahah) XMonad config file causes the same error as above, when asking diagnostics from the line with def (all is fine from the following 5 lines):

import XMonad
import qualified XMonad.Prompt as P

main :: IO ()
main = xmonad def
    { terminal    = "urxvt"
    , modMask     = mod4Mask
    , borderWidth = 3
    , P.borderColor = undefined
    }
bstaletic commented 8 months ago

Managed to repro! Sorry for taking so long. Looks like GetTextPropertyForDiag() does not take into account multi-line diags.

bstaletic commented 8 months ago

Here's the raw data that leads to the error (for the C example):

{
  "start": {
    "line_num": 2,
    "column_num": 1,
    "filepath": "/home/bstaletic/work/test/foo.cpp"
  },
  "end": {
    "line_num": 3,
    "column_num": 11,
    "filepath": "/home/bstaletic/work/test/foo.cpp"
  }
}
[
  {
    "id": "4",
    "col": "1",
    "type_bufnr": "0",
    "end": "0",
    "type": "YcmWarningProperty",
    "length": "13",
    "start": "1"
  },
  {
    "id": "3",
    "col": "1",
    "type_bufnr": "0",
    "end": "0",
    "type": "YcmWarningProperty",
    "length": "13",
    "start": "1"
  }
]

In GetTextPropertyForDiag() we end up subtracting end column of next line from start column of this line, leading to bad length calculation.

@Aster89 Try this patch:

diff --git a/python/ycm/vimsupport.py b/python/ycm/vimsupport.py
index 14798145..61852477 100644
--- a/python/ycm/vimsupport.py
+++ b/python/ycm/vimsupport.py
@@ -284,7 +284,16 @@ def GetTextPropertyForDiag( buffer_number, line_number, diag ):
   range = diag[ 'location_extent' ]
   start = range[ 'start' ]
   end = range[ 'end' ]
-  length = end[ 'column_num' ] - start[ 'column_num' ]
+  start_line = start[ 'line_num' ]
+  end_line = end[ 'line_num' ]
+  if start_line == end_line:
+    length = end[ 'column_num' ] - start[ 'column_num' ]
+  elif start_line == line_number:
+    length = len( vim.buffers[ buffer_number ][ line_number - 1 ] ) - start[ 'column_num' ] + 2
+  elif end_line == line_num:
+    length = end[ 'column_num' ] - 1
+  else:
+    length = len( vim.buffers[ buffer_number ][ line_number - 1 ] )
   if diag[ 'kind' ] == 'ERROR':
     property_name = 'YcmErrorProperty'
   else:
bstaletic commented 8 months ago

The popup placement is very weird on my computer. Though I thing that has something to do with my vim version.

Aster89 commented 8 months ago

The patch works!

Aster89 commented 5 months ago

I've hit another similar error (I'm now on 2b33bf3dc822f6c68b39d235e24efa5508cf9857) with this Haskell code

import Data.Function
getCharAndProcess :: IO ()
getCharAndProcess = do
  fix $ \recurse previous -> do
    c <- getChar -- on this line
    return previous -- or on this line

Trying to show the detailed diag popup on one of the two lines with a comment results in the error above.

See screencast below: asciicast

bstaletic commented 5 months ago

Damnit... I did not realize that the previous fix had a sneaky assumption - all mutliline diagnostics start at line 1.

Here's the patch:

diff --git a/python/ycm/vimsupport.py b/python/ycm/vimsupport.py
index ca603206..826a5b59 100644
--- a/python/ycm/vimsupport.py
+++ b/python/ycm/vimsupport.py
@@ -288,18 +288,22 @@ def GetTextPropertyForDiag( buffer_number, line_number, diag ):
   end_line = end[ 'line_num' ]
   if start_line == end_line:
     length = end[ 'column_num' ] - start[ 'column_num' ]
+    column = start[ 'column_num' ]
   elif start_line == line_number:
     # -1 switches to 0-based indexing.
     current_line_len = len( vim.buffers[ buffer_number ][ line_number - 1 ] )
     # +2 includes the start columnand accounts for properties at the end of line
     # covering \n as well.
     length = current_line_len - start[ 'column_num' ] + 2
+    column = start[ 'column_num' ]
   elif end_line == line_number:
     length = end[ 'column_num' ] - 1
+    column = 1
   else:
     # -1 switches to 0-based indexing.
     # +1 accounts for properties at the end of line covering \n as well.
     length = len( vim.buffers[ buffer_number ][ line_number - 1 ] ) + 1
+    column = 1
   if diag[ 'kind' ] == 'ERROR':
     property_name = 'YcmErrorProperty'
   else:
@@ -309,7 +313,7 @@ def GetTextPropertyForDiag( buffer_number, line_number, diag ):
                           f'{{ "bufnr": { buffer_number }, '
                              f'"types": [ "{ property_name }" ] }} )' )
     return next( filter(
-        lambda p: start[ 'column_num' ] == int( p[ 'col' ] ) and
+        lambda p: column == int( p[ 'col' ] ) and
                   length == int( p[ 'length' ] ),
         vim_props ) )
   else:

I'll make a pull request after adjusting the tests.

Aster89 commented 5 months ago

Sorry for the notification. I had updated YCM but forgotten to close and reopen Vim :D

Aster89 commented 5 months ago

Actually I have indeed found repro steps for a similar error.

The repros are essentially identical to those in my previous message, except that the following one-line Haskell file should be used instead:

foo txt = (tail txt, tail txt)

The error (again, upon trying to show the detailed diag in the popup) is this:

Error detected while processing function <SNR>32_ShowDetailedDiagnostic:
line    3:
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "/home/enrico/.vim/plugged/YouCompleteMe/python/ycm/youcompleteme.py", line 870, in ShowDetailedDiagnostic
    options.pop( 'col' )
KeyError: 'col'
bstaletic commented 5 months ago

This time it was not my oversight! Here's the patch:

diff --git a/python/ycm/youcompleteme.py b/python/ycm/youcompleteme.py
index a09b2ef2..76c8c0a5 100644
--- a/python/ycm/youcompleteme.py
+++ b/python/ycm/youcompleteme.py
@@ -867,7 +867,7 @@ class YouCompleteMe:
               'textpropid': prop[ 'id' ],
               'textprop': prop[ 'type' ],
             } )
-            options.pop( 'col' )
+            options.pop( 'col', None )
         vim.eval( f'{ popup_func }( { json.dumps( lines ) }, '
                                   f'{ json.dumps( options ) } )' )
       else:

Tests incoming.

Aster89 commented 5 months ago

Yes, the above fixes the issue.

bstaletic commented 5 months ago

Fixed in #4219