diff --git a/python/ycm/tests/vimsupport_test.py b/python/ycm/tests/vimsupport_test.py index 74e35a32..65148e21 100644 --- a/python/ycm/tests/vimsupport_test.py +++ b/python/ycm/tests/vimsupport_test.py @@ -544,6 +544,16 @@ def ReplaceChunk_NewlineChunk_test(): 'second line' ], result_buffer ) +def ReplaceChunk_BeyondEndOfFile_test(): + result_buffer = VimBuffer( 'buffer', contents = [ 'first line', + 'second line' ] ) + + start, end = _BuildLocations( 1, 11, 3, 1 ) + vimsupport.ReplaceChunk( start, end, '\n', result_buffer ) + + AssertBuffersAreEqualAsBytes( [ 'first line' ], result_buffer ) + + def _BuildLocations( start_line, start_column, end_line, end_column ): return { 'line_num' : start_line, diff --git a/python/ycm/vimsupport.py b/python/ycm/vimsupport.py index 70a1f295..559e8f33 100644 --- a/python/ycm/vimsupport.py +++ b/python/ycm/vimsupport.py @@ -899,6 +899,17 @@ def ReplaceChunk( start, end, replacement_text, vim_buffer ): start_column = start[ 'column_num' ] - 1 end_column = end[ 'column_num' ] - 1 + # When sending a request to the server, a newline is added to the buffer + # contents to match what gets saved to disk. If the server generates a chunk + # containing that newline, this chunk goes past the Vim buffer contents since + # there is actually no new line. When this happens, recompute the end position + # of where the chunk is applied and remove all trailing characters in the + # chunk. + if end_line >= len( vim_buffer ): + end_column = len( ToBytes( vim_buffer[ -1 ] ) ) + end_line = len( vim_buffer ) - 1 + replacement_text = replacement_text.rstrip() + # NOTE: replacement_text is unicode, but all our offsets are byte offsets, # so we convert to bytes replacement_lines = SplitLines( ToBytes( replacement_text ) )