From 62e46a314e565365b1a46622cdddc5e289a79f47 Mon Sep 17 00:00:00 2001 From: Boris Staletic Date: Wed, 31 Jan 2024 06:31:47 +0100 Subject: [PATCH] Take care of start column in multiline diags for detailed diag popups Previously, we have always used the diagnostics start column of the *starting* line of a multiline diagnostic. This is wrong, as the starting column for a line in the middle of a multiline diagnostic is always 1. Previous patch just happens to work if the start column of the first line of the diagnostic is also 1. --- python/ycm/vimsupport.py | 6 ++- test/diagnostics.test.vim | 82 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 86 insertions(+), 2 deletions(-) diff --git a/python/ycm/vimsupport.py b/python/ycm/vimsupport.py index ca60320645..826a5b59fc 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: diff --git a/test/diagnostics.test.vim b/test/diagnostics.test.vim index 5b98537abe..78671d023f 100644 --- a/test/diagnostics.test.vim +++ b/test/diagnostics.test.vim @@ -348,7 +348,87 @@ function! Test_ShowDetailedDiagnostic_Popup_WithCharacters() %bwipe! endfunction -function! Test_ShowDetailedDiagnostic_Popup_MultilineDiag() +function! Test_ShowDetailedDiagnostic_Popup_MultilineDiagNotFromStartOfLine() + let f = tempname() . '.cc' + execut 'edit' f + call setline( 1, [ + \ 'int main () {', + \ ' int a \', + \ '=\', + \ '=', + \ '3;', + \ '}', + \ ] ) + call youcompleteme#test#setup#WaitForInitialParse( {} ) + + call WaitForAssert( {-> + \ assert_true( + \ py3eval( + \ 'len( ycm_state.CurrentBuffer()._diag_interface._diagnostics )' + \ ) ) } ) + + " Start of multiline diagnostic. + call cursor( [ 2, 9 ] ) + YcmShowDetailedDiagnostic popup + + "let popup_location = screenpos( bufwinid( '%' ), 3, 13 ) + let id = popup_locate( 3, 30 ) + call assert_notequal( 0, id, "Couldn't find popup!" ) + + call youcompleteme#test#popup#CheckPopupPosition( id, { + \ 'visible': 1, + \ 'col': 16, + \ 'line': 3, + \ } ) + call assert_match( + \ "^Variable 'rd' declared const here.*", + \ getbufline( winbufnr(id), 1, '$' )[ 0 ] ) + + " Middle of multiline diagnostic. + call cursor( [ 3, 1 ] ) + YcmShowDetailedDiagnostic popup + + let popup_location = screenpos( bufwinid( '%' ), 3, 13 ) + let id = popup_locate( popup_location[ 'row' ], popup_location[ 'col' ] ) + call assert_notequal( 0, id, "Couldn't find popup!" ) + + " End of multiline diagnostic. + call youcompleteme#test#popup#CheckPopupPosition( id, { + \ 'visible': 1, + \ 'col': 16, + \ 'line': 3, + \ } ) + call assert_match( + \ "^Variable 'rd' declared const here.*", + \ getbufline( winbufnr(id), 1, '$' )[ 0 ] ) + + call cursor( [ 4, 1 ] ) + YcmShowDetailedDiagnostic popup + + let popup_location = screenpos( bufwinid( '%' ), 3, 13 ) + let id = popup_locate( popup_location[ 'row' ], popup_location[ 'col' ] ) + call assert_notequal( 0, id, "Couldn't find popup!" ) + + call youcompleteme#test#popup#CheckPopupPosition( id, { + \ 'visible': 1, + \ 'col': 16, + \ 'line': 3, + \ } ) + call assert_match( + \ "^Variable 'rd' declared const here.*", + \ getbufline( winbufnr(id), 1, '$' )[ 0 ] ) + + " From vim's test_popupwin.vim + " trigger the check for last_cursormoved by going into insert mode + call test_override( 'char_avail', 1 ) + call feedkeys( "ji\", 'xt' ) + call assert_equal( {}, popup_getpos( id ) ) + call test_override( 'ALL', 0 ) + + %bwipe! +endfunction + +function! Test_ShowDetailedDiagnostic_Popup_MultilineDiagFromStartOfLine() let f = tempname() . '.cc' execut 'edit' f call setline( 1, [