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 62e46a3
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 2 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
82 changes: 81 additions & 1 deletion 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

"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\<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 Down

0 comments on commit 62e46a3

Please sign in to comment.