Skip to content

Commit

Permalink
Take care of start column in multiline diags for detailed diag popups
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bstaletic committed Jan 31, 2024
1 parent 2b33bf3 commit 6d07604
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 8 deletions.
6 changes: 5 additions & 1 deletion python/ycm/vimsupport.py
Original file line number Diff line number Diff line change
Expand Up @@ -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' ]

Check warning on line 291 in python/ycm/vimsupport.py

View check run for this annotation

Codecov / codecov/patch

python/ycm/vimsupport.py#L291

Added line #L291 was not covered by tests
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' ]

Check warning on line 298 in python/ycm/vimsupport.py

View check run for this annotation

Codecov / codecov/patch

python/ycm/vimsupport.py#L298

Added line #L298 was not covered by tests
elif end_line == line_number:
length = end[ 'column_num' ] - 1
column = 1

Check warning on line 301 in python/ycm/vimsupport.py

View check run for this annotation

Codecov / codecov/patch

python/ycm/vimsupport.py#L301

Added line #L301 was not covered by tests
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

Check warning on line 306 in python/ycm/vimsupport.py

View check run for this annotation

Codecov / codecov/patch

python/ycm/vimsupport.py#L306

Added line #L306 was not covered by tests
if diag[ 'kind' ] == 'ERROR':
property_name = 'YcmErrorProperty'
else:
Expand All @@ -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:
Expand Down
94 changes: 87 additions & 7 deletions test/diagnostics.test.vim
Original file line number Diff line number Diff line change
Expand Up @@ -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

call assert_equal( len( popup_list() ), 1 )
let id = popup_list()[ 0 ]
call assert_notequal( 0, id, "Couldn't find popup!" )

call youcompleteme#test#popup#CheckPopupPosition( id, {
\ 'visible': 1,
\ 'col': 10,
\ 'line': 3,
\ } )
call assert_match(
\ "^Invalid '==' at end of declaration; did you mean '='?.*",
\ getbufline( winbufnr(id), 1, '$' )[ 0 ] )

" Middle of multiline diagnostic.
call cursor( [ 3, 1 ] )
YcmShowDetailedDiagnostic popup

call assert_equal( len( popup_list() ), 1 )
let id = popup_list()[ 0 ]
call assert_notequal( 0, id, "Couldn't find popup!" )

" End of multiline diagnostic.
call youcompleteme#test#popup#CheckPopupPosition( id, {
\ 'visible': 1,
\ 'col': 10,
\ 'line': 3,
\ } )
call assert_match(
\ "^Invalid '==' at end of declaration; did you mean '='?.*",
\ getbufline( winbufnr(id), 1, '$' )[ 0 ] )

call cursor( [ 4, 1 ] )
YcmShowDetailedDiagnostic popup

call assert_equal( len( popup_list() ), 1 )
let id = popup_list()[ 0 ]
call assert_notequal( 0, id, "Couldn't find popup!" )

call youcompleteme#test#popup#CheckPopupPosition( id, {
\ 'visible': 1,
\ 'col': 10,
\ 'line': 3,
\ } )
call assert_match(
\ "^Invalid '==' at end of declaration; did you mean '='?.*",
\ 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\<Esc>", '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, [
Expand All @@ -371,8 +451,8 @@ function! Test_ShowDetailedDiagnostic_Popup_MultilineDiag()
call cursor( [ 2, 1 ] )
YcmShowDetailedDiagnostic popup

let popup_location = screenpos( bufwinid( '%' ), 3, 13 )
let id = popup_locate( popup_location[ 'row' ], popup_location[ 'col' ] )
call assert_equal( len( popup_list() ), 1 )
let id = popup_list()[ 0 ]
call assert_notequal( 0, id, "Couldn't find popup!" )

call youcompleteme#test#popup#CheckPopupPosition( id, {
Expand All @@ -388,8 +468,8 @@ function! Test_ShowDetailedDiagnostic_Popup_MultilineDiag()
call cursor( [ 3, 9 ] )
YcmShowDetailedDiagnostic popup

let popup_location = screenpos( bufwinid( '%' ), 3, 13 )
let id = popup_locate( popup_location[ 'row' ], popup_location[ 'col' ] )
call assert_equal( len( popup_list() ), 1 )
let id = popup_list()[ 0 ]
call assert_notequal( 0, id, "Couldn't find popup!" )

" End of multiline diagnostic.
Expand All @@ -405,8 +485,8 @@ function! Test_ShowDetailedDiagnostic_Popup_MultilineDiag()
call cursor( [ 4, 5 ] )
YcmShowDetailedDiagnostic popup

let popup_location = screenpos( bufwinid( '%' ), 3, 13 )
let id = popup_locate( popup_location[ 'row' ], popup_location[ 'col' ] )
call assert_equal( len( popup_list() ), 1 )
let id = popup_list()[ 0 ]
call assert_notequal( 0, id, "Couldn't find popup!" )

call youcompleteme#test#popup#CheckPopupPosition( id, {
Expand Down

0 comments on commit 6d07604

Please sign in to comment.