Skip to content

Commit

Permalink
Properly handle diag text property length in multiline diags
Browse files Browse the repository at this point in the history
Previously GetTextPropertyForDiag() assumed it was dealing with a
single-line diagnostic.

For multiline diagnostics we have three additional cases:

- From start of the diagnostic to the end of the line.
  - Happens on the first line of diagnostic.
- From start of the line to the end of the diagnostic.
  - Happens on the last line of diagnostic.
- Whole line
  - Happens between first and last line of diagnostic.
  • Loading branch information
bstaletic committed Nov 5, 2023
1 parent cc9a3ae commit 22a27e6
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 1 deletion.
12 changes: 11 additions & 1 deletion python/ycm/vimsupport.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,17 @@ 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' ]

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

View check run for this annotation

Codecov / codecov/patch

python/ycm/vimsupport.py#L290

Added line #L290 was not covered by tests
elif start_line == line_number:
current_line_len = len( vim.buffers[ buffer_number ][ line_number - 1 ] )
length = current_line_len - start[ 'column_num' ] + 2
elif end_line == line_number:
length = end[ 'column_num' ] - 1

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

View check run for this annotation

Codecov / codecov/patch

python/ycm/vimsupport.py#L294-L295

Added lines #L294 - L295 were not covered by tests
else:
length = len( vim.buffers[ buffer_number ][ line_number - 1 ] )

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

View check run for this annotation

Codecov / codecov/patch

python/ycm/vimsupport.py#L297

Added line #L297 was not covered by tests
if diag[ 'kind' ] == 'ERROR':
property_name = 'YcmErrorProperty'
else:
Expand Down
80 changes: 80 additions & 0 deletions test/diagnostics.test.vim
Original file line number Diff line number Diff line change
Expand Up @@ -341,3 +341,83 @@ function! Test_ShowDetailedDiagnostic_Popup_WithCharacters()

%bwipe!
endfunction

function! Test_ShowDetailedDiagnostic_Popup_MultilineDiag()
let f = tempname() . '.cc'
execut 'edit' f
call setline( 1, [
\ 'int main () {',
\ 'const int &&',
\ ' /* */',
\ ' rd = 1;',
\ 'rd = 4;',
\ '}',
\ ] )
call youcompleteme#test#setup#WaitForInitialParse( {} )

call WaitForAssert( {->
\ assert_true(
\ py3eval(
\ 'len( ycm_state.CurrentBuffer()._diag_interface._diagnostics )'
\ ) ) } )

" Start of multiline diagnostic.
call cursor( [ 2, 1 ] )
YcmShowDetailedDiagnostic popup

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

call youcompleteme#test#popup#CheckPopupPosition( id, {
\ 'visible': 1,
\ 'col': 13,
\ 'line': 3,
\ } )
call assert_match(
\ "^Variable 'rd' declared const here.*",
\ getbufline( winbufnr(id), 1, '$' )[ 0 ] )

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

let expected_popup_location = screenpos( bufwinid( '%' ), 4, 9 )
let id = popup_locate( expected_popup_location[ 'row' ], expected_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': 7,
\ 'line': 4,
\ } )
call assert_match(
\ "^Variable 'rd' declared const here.*",
\ getbufline( winbufnr(id), 1, '$' )[ 0 ] )

call cursor( [ 4, 5 ] )
YcmShowDetailedDiagnostic popup

let expected_popup_location = screenpos( bufwinid( '%' ), 5, 5 )
let id = popup_locate( expected_popup_location[ 'row' ], expected_popup_location[ 'col' ] )
call assert_notequal( 0, id, "Couldn't find popup!" )

call youcompleteme#test#popup#CheckPopupPosition( id, {
\ 'visible': 1,
\ 'col': 7,
\ 'line': 4,
\ } )
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

0 comments on commit 22a27e6

Please sign in to comment.