2016-03-02 21:12:38 -05:00
|
|
|
# coding: utf-8
|
2016-02-28 17:42:18 -05:00
|
|
|
#
|
2015-08-05 17:09:07 -04:00
|
|
|
# Copyright (C) 2015 YouCompleteMe contributors
|
|
|
|
#
|
|
|
|
# This file is part of YouCompleteMe.
|
|
|
|
#
|
|
|
|
# YouCompleteMe is free software: you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
|
|
|
#
|
|
|
|
# YouCompleteMe is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
|
|
|
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
2016-02-27 19:12:24 -05:00
|
|
|
from __future__ import unicode_literals
|
|
|
|
from __future__ import print_function
|
|
|
|
from __future__ import division
|
|
|
|
from __future__ import absolute_import
|
|
|
|
from future import standard_library
|
|
|
|
standard_library.install_aliases()
|
|
|
|
from builtins import * # noqa
|
|
|
|
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
from ycm.test_utils import ExtendedMock, MockVimModule, MockVimCommand
|
2015-09-06 15:07:42 -04:00
|
|
|
MockVimModule()
|
|
|
|
|
2015-08-05 17:09:07 -04:00
|
|
|
from ycm import vimsupport
|
|
|
|
from nose.tools import eq_
|
2016-02-28 17:42:18 -05:00
|
|
|
from hamcrest import assert_that, calling, raises, none, has_entry
|
2015-09-06 15:07:42 -04:00
|
|
|
from mock import MagicMock, call, patch
|
2016-03-25 23:40:17 -04:00
|
|
|
from ycmd.utils import ToBytes, ToUnicode
|
2015-11-07 20:16:13 -05:00
|
|
|
import os
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
import json
|
2015-08-05 17:09:07 -04:00
|
|
|
|
2015-09-12 10:34:47 -04:00
|
|
|
|
2015-08-05 17:09:07 -04:00
|
|
|
def ReplaceChunk_SingleLine_Repl_1_test():
|
|
|
|
# Replace with longer range
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "This is a string" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 1, 1, 5 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
|
|
|
'How long',
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
result_buffer )
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( [ ToBytes( "How long is a string" ) ], result_buffer )
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, 4 )
|
|
|
|
|
|
|
|
# and replace again, using delta
|
|
|
|
start, end = _BuildLocations( 1, 10, 1, 11 )
|
2015-09-12 10:34:47 -04:00
|
|
|
( new_line_offset, new_char_offset ) = vimsupport.ReplaceChunk(
|
2015-08-05 17:09:07 -04:00
|
|
|
start,
|
|
|
|
end,
|
|
|
|
' piece of ',
|
|
|
|
line_offset,
|
|
|
|
char_offset,
|
|
|
|
result_buffer )
|
|
|
|
|
|
|
|
line_offset += new_line_offset
|
|
|
|
char_offset += new_char_offset
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( [ ToBytes( 'How long is a piece of string' ) ], result_buffer )
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( new_line_offset, 0 )
|
|
|
|
eq_( new_char_offset, 9 )
|
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, 13 )
|
|
|
|
|
|
|
|
# and once more, for luck
|
|
|
|
start, end = _BuildLocations( 1, 11, 1, 17 )
|
|
|
|
|
2015-09-12 10:34:47 -04:00
|
|
|
( new_line_offset, new_char_offset ) = vimsupport.ReplaceChunk(
|
2015-08-05 17:09:07 -04:00
|
|
|
start,
|
|
|
|
end,
|
|
|
|
'pie',
|
|
|
|
line_offset,
|
|
|
|
char_offset,
|
|
|
|
result_buffer )
|
|
|
|
|
|
|
|
line_offset += new_line_offset
|
|
|
|
char_offset += new_char_offset
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( [ ToBytes( 'How long is a piece of pie' ) ], result_buffer )
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( new_line_offset, 0 )
|
|
|
|
eq_( new_char_offset, -3 )
|
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, 10 )
|
|
|
|
|
2015-09-12 10:34:47 -04:00
|
|
|
|
2015-08-05 17:09:07 -04:00
|
|
|
def ReplaceChunk_SingleLine_Repl_2_test():
|
|
|
|
# Replace with shorter range
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "This is a string" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 11, 1, 17 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
|
|
|
'test',
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
result_buffer )
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( [ ToBytes( "This is a test" ) ], result_buffer )
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, -2 )
|
|
|
|
|
2015-09-12 10:34:47 -04:00
|
|
|
|
2015-08-05 17:09:07 -04:00
|
|
|
def ReplaceChunk_SingleLine_Repl_3_test():
|
|
|
|
# Replace with equal range
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "This is a string" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 6, 1, 8 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
|
|
|
'be',
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
result_buffer )
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( [ ToBytes( "This be a string" ) ], result_buffer )
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, 0 )
|
|
|
|
|
2015-09-12 10:34:47 -04:00
|
|
|
|
2015-08-05 17:09:07 -04:00
|
|
|
def ReplaceChunk_SingleLine_Add_1_test():
|
|
|
|
# Insert at start
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "is a string" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 1, 1, 1 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
|
|
|
'This ',
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
result_buffer )
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( [ ToBytes( "This is a string" ) ], result_buffer )
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, 5 )
|
|
|
|
|
2015-09-12 10:34:47 -04:00
|
|
|
|
2015-08-05 17:09:07 -04:00
|
|
|
def ReplaceChunk_SingleLine_Add_2_test():
|
|
|
|
# Insert at end
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "This is a " ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 11, 1, 11 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
|
|
|
'string',
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
result_buffer )
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( [ ToBytes( "This is a string" ) ], result_buffer )
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, 6 )
|
|
|
|
|
2015-09-12 10:34:47 -04:00
|
|
|
|
2015-08-05 17:09:07 -04:00
|
|
|
def ReplaceChunk_SingleLine_Add_3_test():
|
|
|
|
# Insert in the middle
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "This is a string" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 8, 1, 8 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
|
|
|
' not',
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
result_buffer )
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( [ ToBytes( "This is not a string" ) ], result_buffer )
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, 4 )
|
|
|
|
|
2015-09-12 10:34:47 -04:00
|
|
|
|
2015-08-05 17:09:07 -04:00
|
|
|
def ReplaceChunk_SingleLine_Del_1_test():
|
|
|
|
# Delete from start
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "This is a string" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 1, 1, 6 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
|
|
|
'',
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
result_buffer )
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( [ ToBytes( "is a string" ) ], result_buffer )
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, -5 )
|
|
|
|
|
2015-09-12 10:34:47 -04:00
|
|
|
|
2015-08-05 17:09:07 -04:00
|
|
|
def ReplaceChunk_SingleLine_Del_2_test():
|
|
|
|
# Delete from end
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "This is a string" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 10, 1, 18 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
|
|
|
'',
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
result_buffer )
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( [ ToBytes( "This is a" ) ], result_buffer )
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, -8 )
|
|
|
|
|
2015-09-12 10:34:47 -04:00
|
|
|
|
2015-08-05 17:09:07 -04:00
|
|
|
def ReplaceChunk_SingleLine_Del_3_test():
|
|
|
|
# Delete from middle
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "This is not a string" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 9, 1, 13 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
|
|
|
'',
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
result_buffer )
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( [ ToBytes( "This is a string" ) ], result_buffer )
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, -4 )
|
|
|
|
|
2015-09-12 10:34:47 -04:00
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
def ReplaceChunk_SingleLine_Unicode_ReplaceUnicodeChars_test():
|
|
|
|
# Replace Unicode characters.
|
|
|
|
result_buffer = [ ToBytes( "This Uniçø∂‰ string is in the middle" ) ]
|
|
|
|
start, end = _BuildLocations( 1, 6, 1, 20 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
|
|
|
'Unicode ',
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
result_buffer )
|
|
|
|
|
|
|
|
eq_( [ ToBytes( "This Unicode string is in the middle" ) ], result_buffer )
|
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, -6 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_SingleLine_Unicode_ReplaceAfterUnicode_test():
|
|
|
|
# Replace ASCII characters after Unicode characters in the line.
|
|
|
|
result_buffer = [ ToBytes( "This Uniçø∂‰ string is in the middle" ) ]
|
|
|
|
start, end = _BuildLocations( 1, 30, 1, 43 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
|
|
|
'fåke',
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
result_buffer )
|
|
|
|
|
|
|
|
eq_( [ ToBytes( "This Uniçø∂‰ string is fåke" ) ], result_buffer )
|
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, -8 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_SingleLine_Unicode_Grown_test():
|
|
|
|
# Replace ASCII characters after Unicode characters in the line.
|
|
|
|
result_buffer = [ ToBytes( "a" ) ]
|
|
|
|
start, end = _BuildLocations( 1, 1, 1, 2 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
|
|
|
'å',
|
|
|
|
0,
|
|
|
|
0,
|
|
|
|
result_buffer )
|
|
|
|
|
|
|
|
eq_( [ ToBytes( "å" ) ], result_buffer )
|
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, 1 ) # Note: byte difference (a = 1 byte, å = 2 bytes)
|
|
|
|
|
|
|
|
|
2015-08-05 17:09:07 -04:00
|
|
|
def ReplaceChunk_RemoveSingleLine_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 2, 1, 3, 1 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, '',
|
|
|
|
0, 0, result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, -1 )
|
|
|
|
eq_( char_offset, 0 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_SingleToMultipleLines_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 2, 2, 2, 2 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'Eb\nbF',
|
|
|
|
0, 0, result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aEb" ),
|
|
|
|
ToBytes( "bFBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, 1 )
|
|
|
|
eq_( char_offset, 1 )
|
|
|
|
|
|
|
|
# now make another change to the "2nd" line
|
|
|
|
start, end = _BuildLocations( 2, 3, 2, 4 )
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
( new_line_offset, new_char_offset ) = vimsupport.ReplaceChunk(
|
|
|
|
start,
|
|
|
|
end,
|
2015-08-05 17:09:07 -04:00
|
|
|
'cccc',
|
|
|
|
line_offset,
|
|
|
|
char_offset,
|
|
|
|
result_buffer )
|
|
|
|
|
|
|
|
line_offset += new_line_offset
|
|
|
|
char_offset += new_char_offset
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aEb" ),
|
|
|
|
ToBytes( "bFBcccc" ),
|
|
|
|
ToBytes( "aCa" ) ], result_buffer )
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( line_offset, 1 )
|
|
|
|
eq_( char_offset, 4 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_SingleToMultipleLines2_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ), ToBytes( "aBa" ), ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 2, 2, 2, 2 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
2015-09-12 10:34:47 -04:00
|
|
|
end,
|
2015-08-05 17:09:07 -04:00
|
|
|
'Eb\nbFb\nG',
|
2015-09-12 10:34:47 -04:00
|
|
|
0,
|
|
|
|
0,
|
2015-08-05 17:09:07 -04:00
|
|
|
result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aEb" ),
|
|
|
|
ToBytes( "bFb" ),
|
|
|
|
ToBytes( "GBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, 2 )
|
|
|
|
eq_( char_offset, 0 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_SingleToMultipleLines3_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ), ToBytes( "aBa" ), ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 2, 2, 2, 2 )
|
2015-09-12 10:34:47 -04:00
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
2015-08-05 17:09:07 -04:00
|
|
|
'Eb\nbFb\nbGb',
|
2015-09-12 10:34:47 -04:00
|
|
|
0,
|
|
|
|
0,
|
2015-08-05 17:09:07 -04:00
|
|
|
result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aEb" ),
|
|
|
|
ToBytes( "bFb" ),
|
|
|
|
ToBytes( "bGbBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, 2 )
|
|
|
|
eq_( char_offset, 2 )
|
|
|
|
|
2015-09-12 10:34:47 -04:00
|
|
|
|
2015-08-05 17:09:07 -04:00
|
|
|
def ReplaceChunk_SingleToMultipleLinesReplace_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ), ToBytes( "aBa" ), ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 2, 1, 4 )
|
2015-09-12 10:34:47 -04:00
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
2015-08-05 17:09:07 -04:00
|
|
|
'Eb\nbFb\nbGb',
|
2015-09-12 10:34:47 -04:00
|
|
|
0,
|
|
|
|
0,
|
2015-08-05 17:09:07 -04:00
|
|
|
result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aEb" ),
|
|
|
|
ToBytes( "bFb" ),
|
|
|
|
ToBytes( "bGb" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, 2 )
|
|
|
|
eq_( char_offset, 0 )
|
|
|
|
|
2015-09-12 10:34:47 -04:00
|
|
|
|
2015-08-05 17:09:07 -04:00
|
|
|
def ReplaceChunk_SingleToMultipleLinesReplace_2_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 2, 1, 4 )
|
2015-09-12 10:34:47 -04:00
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
2015-08-05 17:09:07 -04:00
|
|
|
'Eb\nbFb\nbGb',
|
2015-09-12 10:34:47 -04:00
|
|
|
0,
|
|
|
|
0,
|
2015-08-05 17:09:07 -04:00
|
|
|
result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aEb" ),
|
|
|
|
ToBytes( "bFb" ),
|
|
|
|
ToBytes( "bGb" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, 2 )
|
|
|
|
eq_( char_offset, 0 )
|
|
|
|
|
|
|
|
# now do a subsequent change (insert at end of line "1")
|
|
|
|
start, end = _BuildLocations( 1, 4, 1, 4 )
|
2015-09-12 10:34:47 -04:00
|
|
|
( new_line_offset, new_char_offset ) = vimsupport.ReplaceChunk(
|
2015-08-05 17:09:07 -04:00
|
|
|
start,
|
|
|
|
end,
|
|
|
|
'cccc',
|
|
|
|
line_offset,
|
|
|
|
char_offset,
|
|
|
|
result_buffer )
|
|
|
|
|
|
|
|
line_offset += new_line_offset
|
|
|
|
char_offset += new_char_offset
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( [ ToBytes( "aEb" ),
|
|
|
|
ToBytes( "bFb" ),
|
|
|
|
ToBytes( "bGbcccc" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ) ], result_buffer )
|
2015-08-05 17:09:07 -04:00
|
|
|
|
|
|
|
eq_( line_offset, 2 )
|
|
|
|
eq_( char_offset, 4 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_MultipleLinesToSingleLine_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ), ToBytes( "aBa" ), ToBytes( "aCaaaa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 2, 2, 3, 2 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'E',
|
|
|
|
0, 0, result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aAa" ), ToBytes( "aECaaaa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, -1 )
|
|
|
|
eq_( char_offset, 1 )
|
|
|
|
|
|
|
|
# make another modification applying offsets
|
|
|
|
start, end = _BuildLocations( 3, 3, 3, 4 )
|
2015-09-12 10:34:47 -04:00
|
|
|
( new_line_offset, new_char_offset ) = vimsupport.ReplaceChunk(
|
2015-08-05 17:09:07 -04:00
|
|
|
start,
|
|
|
|
end,
|
|
|
|
'cccc',
|
|
|
|
line_offset,
|
|
|
|
char_offset,
|
|
|
|
result_buffer )
|
|
|
|
|
|
|
|
line_offset += new_line_offset
|
|
|
|
char_offset += new_char_offset
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aECccccaaa" ) ], result_buffer )
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( line_offset, -1 )
|
|
|
|
eq_( char_offset, 4 )
|
|
|
|
|
|
|
|
# and another, for luck
|
|
|
|
start, end = _BuildLocations( 3, 4, 3, 5 )
|
2015-09-12 10:34:47 -04:00
|
|
|
( new_line_offset, new_char_offset ) = vimsupport.ReplaceChunk(
|
2015-08-05 17:09:07 -04:00
|
|
|
start,
|
|
|
|
end,
|
|
|
|
'dd\ndd',
|
|
|
|
line_offset,
|
|
|
|
char_offset,
|
|
|
|
result_buffer )
|
|
|
|
|
|
|
|
line_offset += new_line_offset
|
|
|
|
char_offset += new_char_offset
|
2015-09-12 10:34:47 -04:00
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aECccccdd" ),
|
|
|
|
ToBytes( "ddaa" ) ],
|
|
|
|
result_buffer )
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, -2 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_MultipleLinesToSameMultipleLines_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ),
|
|
|
|
ToBytes( "aDe" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 2, 2, 3, 2 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'Eb\nbF',
|
|
|
|
0, 0, result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aEb" ),
|
|
|
|
ToBytes( "bFCa" ),
|
|
|
|
ToBytes( "aDe" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, 1 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_MultipleLinesToMoreMultipleLines_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ),
|
|
|
|
ToBytes( "aDe" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 2, 2, 3, 2 )
|
2015-09-12 10:34:47 -04:00
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
2015-08-05 17:09:07 -04:00
|
|
|
'Eb\nbFb\nbG',
|
2015-09-12 10:34:47 -04:00
|
|
|
0,
|
|
|
|
0,
|
2015-08-05 17:09:07 -04:00
|
|
|
result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aEb" ),
|
|
|
|
ToBytes( "bFb" ),
|
|
|
|
ToBytes( "bGCa" ),
|
|
|
|
ToBytes( "aDe" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, 1 )
|
|
|
|
eq_( char_offset, 1 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_MultipleLinesToLessMultipleLines_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ),
|
|
|
|
ToBytes( "aDe" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 2, 3, 2 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'Eb\nbF',
|
|
|
|
0, 0, result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aEb" ), ToBytes( "bFCa" ), ToBytes( "aDe" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, -1 )
|
|
|
|
eq_( char_offset, 1 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_MultipleLinesToEvenLessMultipleLines_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ),
|
|
|
|
ToBytes( "aDe" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 2, 4, 2 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'Eb\nbF',
|
|
|
|
0, 0, result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aEb" ), ToBytes( "bFDe" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, -2 )
|
|
|
|
eq_( char_offset, 1 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_SpanBufferEdge_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 1, 1, 3 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'bDb',
|
|
|
|
0, 0, result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "bDba" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, 1 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_DeleteTextInLine_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 2, 2, 2, 3 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, '',
|
|
|
|
0, 0, result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, -1 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_AddTextInLine_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 2, 2, 2, 2 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'bDb',
|
|
|
|
0, 0, result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "abDbBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, 3 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_ReplaceTextInLine_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 2, 2, 2, 3 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'bDb',
|
|
|
|
0, 0, result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "abDba" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, 2 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_SingleLineOffsetWorks_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 1, 1, 2 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'bDb',
|
|
|
|
1, 1, result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "abDba" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, 0 )
|
|
|
|
eq_( char_offset, 2 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_SingleLineToMultipleLinesOffsetWorks_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 1, 1, 2 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'Db\nE',
|
|
|
|
1, 1, result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aDb" ),
|
|
|
|
ToBytes( "Ea" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, 1 )
|
|
|
|
eq_( char_offset, -1 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_MultipleLinesToSingleLineOffsetWorks_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 1, 1, 2, 2 )
|
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start, end, 'bDb',
|
|
|
|
1, 1, result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "abDbCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, -1 )
|
|
|
|
eq_( char_offset, 3 )
|
|
|
|
|
|
|
|
|
|
|
|
def ReplaceChunk_MultipleLineOffsetWorks_test():
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "aBa" ),
|
|
|
|
ToBytes( "aCa" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
start, end = _BuildLocations( 3, 1, 4, 3 )
|
2015-09-12 10:34:47 -04:00
|
|
|
( line_offset, char_offset ) = vimsupport.ReplaceChunk( start,
|
|
|
|
end,
|
2015-08-05 17:09:07 -04:00
|
|
|
'bDb\nbEb\nbFb',
|
2015-09-12 10:34:47 -04:00
|
|
|
-1,
|
|
|
|
1,
|
2015-08-05 17:09:07 -04:00
|
|
|
result_buffer )
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "aAa" ),
|
|
|
|
ToBytes( "abDb" ),
|
|
|
|
ToBytes( "bEb" ),
|
|
|
|
ToBytes( "bFba" ) ]
|
2015-08-05 17:09:07 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
eq_( line_offset, 1 )
|
|
|
|
eq_( char_offset, 1 )
|
|
|
|
|
|
|
|
|
|
|
|
def _BuildLocations( start_line, start_column, end_line, end_column ):
|
2015-09-12 10:34:47 -04:00
|
|
|
return {
|
|
|
|
'line_num' : start_line,
|
2015-08-05 17:09:07 -04:00
|
|
|
'column_num': start_column,
|
|
|
|
}, {
|
2015-09-12 10:34:47 -04:00
|
|
|
'line_num' : end_line,
|
2015-08-05 17:09:07 -04:00
|
|
|
'column_num': end_column,
|
|
|
|
}
|
2015-09-12 11:06:17 -04:00
|
|
|
|
|
|
|
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
def ReplaceChunksInBuffer_SortedChunks_test():
|
2015-09-12 11:06:17 -04:00
|
|
|
chunks = [
|
|
|
|
_BuildChunk( 1, 4, 1, 4, '('),
|
|
|
|
_BuildChunk( 1, 11, 1, 11, ')' )
|
|
|
|
]
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "CT<10 >> 2> ct" ) ]
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
vimsupport.ReplaceChunksInBuffer( chunks, result_buffer, None )
|
2015-09-12 11:06:17 -04:00
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "CT<(10 >> 2)> ct" ) ]
|
2015-09-12 11:06:17 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
|
|
|
|
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
def ReplaceChunksInBuffer_UnsortedChunks_test():
|
2015-09-12 11:06:17 -04:00
|
|
|
chunks = [
|
|
|
|
_BuildChunk( 1, 11, 1, 11, ')'),
|
|
|
|
_BuildChunk( 1, 4, 1, 4, '(' )
|
|
|
|
]
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
result_buffer = [ ToBytes( "CT<10 >> 2> ct" ) ]
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
vimsupport.ReplaceChunksInBuffer( chunks, result_buffer, None )
|
2015-09-12 11:06:17 -04:00
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
expected_buffer = [ ToBytes( "CT<(10 >> 2)> ct" ) ]
|
2015-09-12 11:06:17 -04:00
|
|
|
eq_( expected_buffer, result_buffer )
|
|
|
|
|
|
|
|
|
2016-02-27 19:12:24 -05:00
|
|
|
class MockBuffer( object ):
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
"""An object that looks like a vim.buffer object, enough for ReplaceChunk to
|
|
|
|
generate a location list"""
|
|
|
|
|
|
|
|
def __init__( self, lines, name, number ):
|
2016-03-25 23:40:17 -04:00
|
|
|
self.lines = [ ToBytes( x ) for x in lines ]
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
self.name = name
|
|
|
|
self.number = number
|
|
|
|
|
|
|
|
|
|
|
|
def __getitem__( self, index ):
|
2016-03-25 23:40:17 -04:00
|
|
|
""" Return the bytes for a given line at index |index| """
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
return self.lines[ index ]
|
|
|
|
|
|
|
|
|
|
|
|
def __len__( self ):
|
|
|
|
return len( self.lines )
|
|
|
|
|
|
|
|
|
|
|
|
def __setitem__( self, key, value ):
|
|
|
|
return self.lines.__setitem__( key, value )
|
|
|
|
|
|
|
|
|
2016-03-25 23:40:17 -04:00
|
|
|
def GetLines( self ):
|
|
|
|
""" Return the contents of the buffer as a list of unicode strings"""
|
|
|
|
return [ ToUnicode( x ) for x in self.lines ]
|
|
|
|
|
|
|
|
|
2016-05-31 04:40:25 -04:00
|
|
|
@patch( 'ycm.vimsupport.VariableExists', return_value = False )
|
|
|
|
@patch( 'ycm.vimsupport.SetFittingHeightForCurrentWindow' )
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
@patch( 'ycm.vimsupport.GetBufferNumberForFilename',
|
|
|
|
return_value=1,
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'ycm.vimsupport.BufferIsVisible',
|
|
|
|
return_value=True,
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'ycm.vimsupport.OpenFilename' )
|
|
|
|
@patch( 'ycm.vimsupport.EchoTextVimWidth', new_callable=ExtendedMock )
|
|
|
|
@patch( 'vim.eval', new_callable=ExtendedMock )
|
|
|
|
@patch( 'vim.command', new_callable=ExtendedMock )
|
|
|
|
def ReplaceChunks_SingleFile_Open_test( vim_command,
|
|
|
|
vim_eval,
|
|
|
|
echo_text_vim_width,
|
|
|
|
open_filename,
|
|
|
|
buffer_is_visible,
|
2016-05-31 04:40:25 -04:00
|
|
|
get_buffer_number_for_filename,
|
|
|
|
set_fitting_height,
|
|
|
|
variable_exists ):
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
|
|
|
|
chunks = [
|
|
|
|
_BuildChunk( 1, 1, 2, 1, 'replacement', 'single_file' )
|
|
|
|
]
|
|
|
|
|
|
|
|
result_buffer = MockBuffer( [
|
|
|
|
'line1',
|
|
|
|
'line2',
|
|
|
|
'line3',
|
|
|
|
], 'single_file', 1 )
|
|
|
|
|
|
|
|
with patch( 'vim.buffers', [ None, result_buffer, None ] ):
|
|
|
|
vimsupport.ReplaceChunks( chunks )
|
|
|
|
|
|
|
|
# Ensure that we applied the replacement correctly
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( result_buffer.GetLines(), [
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
'replacementline2',
|
|
|
|
'line3',
|
|
|
|
] )
|
|
|
|
|
|
|
|
# GetBufferNumberForFilename is called twice:
|
|
|
|
# - once to the check if we would require opening the file (so that we can
|
|
|
|
# raise a warning)
|
|
|
|
# - once whilst applying the changes
|
|
|
|
get_buffer_number_for_filename.assert_has_exact_calls( [
|
|
|
|
call( 'single_file', False ),
|
|
|
|
call( 'single_file', False ),
|
|
|
|
] )
|
|
|
|
|
|
|
|
# BufferIsVisible is called twice for the same reasons as above
|
|
|
|
buffer_is_visible.assert_has_exact_calls( [
|
|
|
|
call( 1 ),
|
|
|
|
call( 1 ),
|
|
|
|
] )
|
|
|
|
|
|
|
|
# we don't attempt to open any files
|
|
|
|
open_filename.assert_not_called()
|
|
|
|
|
|
|
|
# But we do set the quickfix list
|
|
|
|
vim_eval.assert_has_exact_calls( [
|
|
|
|
call( 'setqflist( {0} )'.format( json.dumps( [ {
|
|
|
|
'bufnr': 1,
|
|
|
|
'filename': 'single_file',
|
|
|
|
'lnum': 1,
|
|
|
|
'col': 1,
|
|
|
|
'text': 'replacement',
|
|
|
|
'type': 'F'
|
|
|
|
} ] ) ) ),
|
|
|
|
] )
|
2016-05-31 04:40:25 -04:00
|
|
|
vim_command.assert_has_exact_calls( [
|
|
|
|
call( 'botright copen' ),
|
|
|
|
call( 'silent! wincmd p' )
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
] )
|
2016-05-31 04:40:25 -04:00
|
|
|
set_fitting_height.assert_called_once_with()
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
|
|
|
|
# And it is ReplaceChunks that prints the message showing the number of
|
|
|
|
# changes
|
|
|
|
echo_text_vim_width.assert_has_exact_calls( [
|
|
|
|
call( 'Applied 1 changes' ),
|
|
|
|
] )
|
|
|
|
|
|
|
|
|
2016-05-31 04:40:25 -04:00
|
|
|
@patch( 'ycm.vimsupport.VariableExists', return_value = False )
|
|
|
|
@patch( 'ycm.vimsupport.SetFittingHeightForCurrentWindow' )
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
@patch( 'ycm.vimsupport.GetBufferNumberForFilename',
|
|
|
|
side_effect=[ -1, -1, 1 ],
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'ycm.vimsupport.BufferIsVisible',
|
|
|
|
side_effect=[ False, False, True ],
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'ycm.vimsupport.OpenFilename',
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'ycm.vimsupport.EchoTextVimWidth', new_callable=ExtendedMock )
|
|
|
|
@patch( 'ycm.vimsupport.Confirm',
|
|
|
|
return_value=True,
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'vim.eval', return_value=10, new_callable=ExtendedMock )
|
|
|
|
@patch( 'vim.command', new_callable=ExtendedMock )
|
|
|
|
def ReplaceChunks_SingleFile_NotOpen_test( vim_command,
|
|
|
|
vim_eval,
|
|
|
|
confirm,
|
|
|
|
echo_text_vim_width,
|
|
|
|
open_filename,
|
|
|
|
buffer_is_visible,
|
2016-05-31 04:40:25 -04:00
|
|
|
get_buffer_number_for_filename,
|
|
|
|
set_fitting_height,
|
|
|
|
variable_exists ):
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
|
|
|
|
chunks = [
|
|
|
|
_BuildChunk( 1, 1, 2, 1, 'replacement', 'single_file' )
|
|
|
|
]
|
|
|
|
|
|
|
|
result_buffer = MockBuffer( [
|
|
|
|
'line1',
|
|
|
|
'line2',
|
|
|
|
'line3',
|
|
|
|
], 'single_file', 1 )
|
|
|
|
|
|
|
|
with patch( 'vim.buffers', [ None, result_buffer, None ] ):
|
|
|
|
vimsupport.ReplaceChunks( chunks )
|
|
|
|
|
|
|
|
# We checked if it was OK to open the file
|
|
|
|
confirm.assert_has_exact_calls( [
|
|
|
|
call( vimsupport.FIXIT_OPENING_BUFFERS_MESSAGE_FORMAT.format( 1 ) )
|
|
|
|
] )
|
|
|
|
|
|
|
|
# Ensure that we applied the replacement correctly
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( result_buffer.GetLines(), [
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
'replacementline2',
|
|
|
|
'line3',
|
|
|
|
] )
|
|
|
|
|
|
|
|
# GetBufferNumberForFilename is called 3 times. The return values are set in
|
|
|
|
# the @patch call above:
|
|
|
|
# - once to the check if we would require opening the file (so that we can
|
|
|
|
# raise a warning) (-1 return)
|
|
|
|
# - once whilst applying the changes (-1 return)
|
|
|
|
# - finally after calling OpenFilename (1 return)
|
|
|
|
get_buffer_number_for_filename.assert_has_exact_calls( [
|
|
|
|
call( 'single_file', False ),
|
|
|
|
call( 'single_file', False ),
|
|
|
|
call( 'single_file', False ),
|
|
|
|
] )
|
|
|
|
|
|
|
|
# BufferIsVisible is called 3 times for the same reasons as above, with the
|
|
|
|
# return of each one
|
|
|
|
buffer_is_visible.assert_has_exact_calls( [
|
|
|
|
call( -1 ),
|
|
|
|
call( -1 ),
|
|
|
|
call( 1 ),
|
|
|
|
] )
|
|
|
|
|
|
|
|
# We open 'single_file' as expected.
|
|
|
|
open_filename.assert_called_with( 'single_file', {
|
|
|
|
'focus': True,
|
|
|
|
'fix': True,
|
|
|
|
'size': 10
|
|
|
|
} )
|
|
|
|
|
2016-05-31 04:40:25 -04:00
|
|
|
# And close it again, then show the quickfix window.
|
|
|
|
vim_command.assert_has_exact_calls( [
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
call( 'lclose' ),
|
|
|
|
call( 'hide' ),
|
2016-05-31 04:40:25 -04:00
|
|
|
call( 'botright copen' ),
|
|
|
|
call( 'silent! wincmd p' )
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
] )
|
2016-05-31 04:40:25 -04:00
|
|
|
set_fitting_height.assert_called_once_with()
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
|
|
|
|
# And update the quickfix list
|
|
|
|
vim_eval.assert_has_exact_calls( [
|
|
|
|
call( '&previewheight' ),
|
|
|
|
call( 'setqflist( {0} )'.format( json.dumps( [ {
|
|
|
|
'bufnr': 1,
|
|
|
|
'filename': 'single_file',
|
|
|
|
'lnum': 1,
|
|
|
|
'col': 1,
|
|
|
|
'text': 'replacement',
|
|
|
|
'type': 'F'
|
|
|
|
} ] ) ) ),
|
|
|
|
] )
|
|
|
|
|
|
|
|
# And it is ReplaceChunks that prints the message showing the number of
|
|
|
|
# changes
|
|
|
|
echo_text_vim_width.assert_has_exact_calls( [
|
|
|
|
call( 'Applied 1 changes' ),
|
|
|
|
] )
|
|
|
|
|
|
|
|
|
|
|
|
@patch( 'ycm.vimsupport.GetBufferNumberForFilename',
|
|
|
|
side_effect=[ -1, -1, 1 ],
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'ycm.vimsupport.BufferIsVisible',
|
|
|
|
side_effect=[ False, False, True ],
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'ycm.vimsupport.OpenFilename',
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'ycm.vimsupport.EchoTextVimWidth',
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'ycm.vimsupport.Confirm',
|
|
|
|
return_value=False,
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'vim.eval',
|
|
|
|
return_value=10,
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'vim.command', new_callable=ExtendedMock )
|
|
|
|
def ReplaceChunks_User_Declines_To_Open_File_test(
|
|
|
|
vim_command,
|
|
|
|
vim_eval,
|
|
|
|
confirm,
|
|
|
|
echo_text_vim_width,
|
|
|
|
open_filename,
|
|
|
|
buffer_is_visible,
|
|
|
|
get_buffer_number_for_filename ):
|
|
|
|
|
|
|
|
# Same as above, except the user selects Cancel when asked if they should
|
|
|
|
# allow us to open lots of (ahem, 1) file.
|
|
|
|
|
|
|
|
chunks = [
|
|
|
|
_BuildChunk( 1, 1, 2, 1, 'replacement', 'single_file' )
|
|
|
|
]
|
|
|
|
|
|
|
|
result_buffer = MockBuffer( [
|
|
|
|
'line1',
|
|
|
|
'line2',
|
|
|
|
'line3',
|
|
|
|
], 'single_file', 1 )
|
|
|
|
|
|
|
|
with patch( 'vim.buffers', [ None, result_buffer, None ] ):
|
|
|
|
vimsupport.ReplaceChunks( chunks )
|
|
|
|
|
|
|
|
# We checked if it was OK to open the file
|
|
|
|
confirm.assert_has_exact_calls( [
|
|
|
|
call( vimsupport.FIXIT_OPENING_BUFFERS_MESSAGE_FORMAT.format( 1 ) )
|
|
|
|
] )
|
|
|
|
|
|
|
|
# Ensure that buffer is not changed
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( result_buffer.GetLines(), [
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
'line1',
|
|
|
|
'line2',
|
|
|
|
'line3',
|
|
|
|
] )
|
|
|
|
|
|
|
|
# GetBufferNumberForFilename is called once. The return values are set in
|
|
|
|
# the @patch call above:
|
|
|
|
# - once to the check if we would require opening the file (so that we can
|
|
|
|
# raise a warning) (-1 return)
|
|
|
|
get_buffer_number_for_filename.assert_has_exact_calls( [
|
|
|
|
call( 'single_file', False ),
|
|
|
|
] )
|
|
|
|
|
|
|
|
# BufferIsVisible is called once for the above file, which wasn't visible.
|
|
|
|
buffer_is_visible.assert_has_exact_calls( [
|
|
|
|
call( -1 ),
|
|
|
|
] )
|
|
|
|
|
|
|
|
# We don't attempt to open any files or update any quickfix list or anything
|
|
|
|
# like that
|
|
|
|
open_filename.assert_not_called()
|
|
|
|
vim_eval.assert_not_called()
|
|
|
|
vim_command.assert_not_called()
|
|
|
|
echo_text_vim_width.assert_not_called()
|
|
|
|
|
|
|
|
|
|
|
|
@patch( 'ycm.vimsupport.GetBufferNumberForFilename',
|
|
|
|
side_effect=[ -1, -1, 1 ],
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
# Key difference is here: In the final check, BufferIsVisible returns False
|
|
|
|
@patch( 'ycm.vimsupport.BufferIsVisible',
|
|
|
|
side_effect=[ False, False, False ],
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'ycm.vimsupport.OpenFilename',
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'ycm.vimsupport.EchoTextVimWidth',
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'ycm.vimsupport.Confirm',
|
|
|
|
return_value=True,
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'vim.eval',
|
|
|
|
return_value=10,
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'vim.command',
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
def ReplaceChunks_User_Aborts_Opening_File_test(
|
|
|
|
vim_command,
|
|
|
|
vim_eval,
|
|
|
|
confirm,
|
|
|
|
echo_text_vim_width,
|
|
|
|
open_filename,
|
|
|
|
buffer_is_visible,
|
|
|
|
get_buffer_number_for_filename ):
|
|
|
|
|
|
|
|
# Same as above, except the user selects Abort or Quick during the
|
|
|
|
# "swap-file-found" dialog
|
|
|
|
|
|
|
|
chunks = [
|
|
|
|
_BuildChunk( 1, 1, 2, 1, 'replacement', 'single_file' )
|
|
|
|
]
|
|
|
|
|
|
|
|
result_buffer = MockBuffer( [
|
|
|
|
'line1',
|
|
|
|
'line2',
|
|
|
|
'line3',
|
|
|
|
], 'single_file', 1 )
|
|
|
|
|
|
|
|
with patch( 'vim.buffers', [ None, result_buffer, None ] ):
|
|
|
|
assert_that( calling( vimsupport.ReplaceChunks ).with_args( chunks ),
|
|
|
|
raises( RuntimeError,
|
|
|
|
'Unable to open file: single_file\nFixIt/Refactor operation '
|
|
|
|
'aborted prior to completion. Your files have not been '
|
|
|
|
'fully updated. Please use undo commands to revert the '
|
|
|
|
'applied changes.' ) )
|
|
|
|
|
|
|
|
# We checked if it was OK to open the file
|
|
|
|
confirm.assert_has_exact_calls( [
|
|
|
|
call( vimsupport.FIXIT_OPENING_BUFFERS_MESSAGE_FORMAT.format( 1 ) )
|
|
|
|
] )
|
|
|
|
|
|
|
|
# Ensure that buffer is not changed
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( result_buffer.GetLines(), [
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
'line1',
|
|
|
|
'line2',
|
|
|
|
'line3',
|
|
|
|
] )
|
|
|
|
|
|
|
|
# We tried to open this file
|
|
|
|
open_filename.assert_called_with( "single_file", {
|
|
|
|
'focus': True,
|
|
|
|
'fix': True,
|
|
|
|
'size': 10
|
|
|
|
} )
|
|
|
|
vim_eval.assert_called_with( "&previewheight" )
|
|
|
|
|
|
|
|
# But raised an exception before issuing the message at the end
|
|
|
|
echo_text_vim_width.assert_not_called()
|
|
|
|
|
|
|
|
|
2016-05-31 04:40:25 -04:00
|
|
|
@patch( 'ycm.vimsupport.VariableExists', return_value = False )
|
|
|
|
@patch( 'ycm.vimsupport.SetFittingHeightForCurrentWindow' )
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
@patch( 'ycm.vimsupport.GetBufferNumberForFilename', side_effect=[
|
|
|
|
22, # first_file (check)
|
|
|
|
-1, # another_file (check)
|
|
|
|
22, # first_file (apply)
|
|
|
|
-1, # another_file (apply)
|
|
|
|
19, # another_file (check after open)
|
|
|
|
],
|
|
|
|
new_callable=ExtendedMock )
|
|
|
|
@patch( 'ycm.vimsupport.BufferIsVisible', side_effect=[
|
|
|
|
True, # first_file (check)
|
|
|
|
False, # second_file (check)
|
|
|
|
True, # first_file (apply)
|
|
|
|
False, # second_file (apply)
|
|
|
|
True, # side_effect (check after open)
|
|
|
|
],
|
|
|
|
new_callable=ExtendedMock)
|
|
|
|
@patch( 'ycm.vimsupport.OpenFilename',
|
|
|
|
new_callable=ExtendedMock)
|
|
|
|
@patch( 'ycm.vimsupport.EchoTextVimWidth',
|
|
|
|
new_callable=ExtendedMock)
|
|
|
|
@patch( 'ycm.vimsupport.Confirm', return_value=True,
|
|
|
|
new_callable=ExtendedMock)
|
|
|
|
@patch( 'vim.eval', return_value=10,
|
|
|
|
new_callable=ExtendedMock)
|
|
|
|
@patch( 'vim.command',
|
|
|
|
new_callable=ExtendedMock)
|
|
|
|
def ReplaceChunks_MultiFile_Open_test( vim_command,
|
|
|
|
vim_eval,
|
|
|
|
confirm,
|
|
|
|
echo_text_vim_width,
|
|
|
|
open_filename,
|
|
|
|
buffer_is_visible,
|
2016-05-31 04:40:25 -04:00
|
|
|
get_buffer_number_for_filename,
|
|
|
|
set_fitting_height,
|
|
|
|
variable_exists ):
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
|
|
|
|
# Chunks are split across 2 files, one is already open, one isn't
|
|
|
|
|
|
|
|
chunks = [
|
|
|
|
_BuildChunk( 1, 1, 2, 1, 'first_file_replacement ', '1_first_file' ),
|
|
|
|
_BuildChunk( 2, 1, 2, 1, 'second_file_replacement ', '2_another_file' ),
|
|
|
|
]
|
|
|
|
|
|
|
|
first_file = MockBuffer( [
|
|
|
|
'line1',
|
|
|
|
'line2',
|
|
|
|
'line3',
|
|
|
|
], '1_first_file', 22 )
|
|
|
|
another_file = MockBuffer( [
|
|
|
|
'another line1',
|
|
|
|
'ACME line2',
|
|
|
|
], '2_another_file', 19 )
|
|
|
|
|
|
|
|
vim_buffers = [ None ] * 23
|
|
|
|
vim_buffers[ 22 ] = first_file
|
|
|
|
vim_buffers[ 19 ] = another_file
|
|
|
|
|
|
|
|
with patch( 'vim.buffers', vim_buffers ):
|
|
|
|
vimsupport.ReplaceChunks( chunks )
|
|
|
|
|
|
|
|
# We checked for the right file names
|
|
|
|
get_buffer_number_for_filename.assert_has_exact_calls( [
|
|
|
|
call( '1_first_file', False ),
|
|
|
|
call( '2_another_file', False ),
|
|
|
|
call( '1_first_file', False ),
|
|
|
|
call( '2_another_file', False ),
|
|
|
|
call( '2_another_file', False ),
|
|
|
|
] )
|
|
|
|
|
|
|
|
# We checked if it was OK to open the file
|
|
|
|
confirm.assert_has_exact_calls( [
|
|
|
|
call( vimsupport.FIXIT_OPENING_BUFFERS_MESSAGE_FORMAT.format( 1 ) )
|
|
|
|
] )
|
|
|
|
|
|
|
|
# Ensure that buffers are updated
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( another_file.GetLines(), [
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
'another line1',
|
|
|
|
'second_file_replacement ACME line2',
|
|
|
|
] )
|
2016-03-25 23:40:17 -04:00
|
|
|
eq_( first_file.GetLines(), [
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
'first_file_replacement line2',
|
|
|
|
'line3',
|
|
|
|
] )
|
|
|
|
|
|
|
|
# We open '2_another_file' as expected.
|
|
|
|
open_filename.assert_called_with( '2_another_file', {
|
|
|
|
'focus': True,
|
|
|
|
'fix': True,
|
|
|
|
'size': 10
|
|
|
|
} )
|
|
|
|
|
2016-05-31 04:40:25 -04:00
|
|
|
# And close it again, then show the quickfix window.
|
|
|
|
vim_command.assert_has_exact_calls( [
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
call( 'lclose' ),
|
|
|
|
call( 'hide' ),
|
2016-05-31 04:40:25 -04:00
|
|
|
call( 'botright copen' ),
|
|
|
|
call( 'silent! wincmd p' )
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
] )
|
2016-05-31 04:40:25 -04:00
|
|
|
set_fitting_height.assert_called_once_with()
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
|
|
|
|
# And update the quickfix list with each entry
|
|
|
|
vim_eval.assert_has_exact_calls( [
|
|
|
|
call( '&previewheight' ),
|
|
|
|
call( 'setqflist( {0} )'.format( json.dumps( [ {
|
|
|
|
'bufnr': 22,
|
|
|
|
'filename': '1_first_file',
|
|
|
|
'lnum': 1,
|
|
|
|
'col': 1,
|
|
|
|
'text': 'first_file_replacement ',
|
|
|
|
'type': 'F'
|
|
|
|
}, {
|
|
|
|
'bufnr': 19,
|
|
|
|
'filename': '2_another_file',
|
|
|
|
'lnum': 2,
|
|
|
|
'col': 1,
|
|
|
|
'text': 'second_file_replacement ',
|
|
|
|
'type': 'F'
|
|
|
|
} ] ) ) ),
|
|
|
|
] )
|
|
|
|
|
|
|
|
# And it is ReplaceChunks that prints the message showing the number of
|
|
|
|
# changes
|
|
|
|
echo_text_vim_width.assert_has_exact_calls( [
|
|
|
|
call( 'Applied 2 changes' ),
|
|
|
|
] )
|
|
|
|
|
|
|
|
|
|
|
|
def _BuildChunk( start_line,
|
|
|
|
start_column,
|
|
|
|
end_line,
|
|
|
|
end_column,
|
|
|
|
replacement_text, filepath='test_file_name' ):
|
2015-09-12 11:06:17 -04:00
|
|
|
return {
|
|
|
|
'range': {
|
|
|
|
'start': {
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
'filepath': filepath,
|
2015-09-12 11:06:17 -04:00
|
|
|
'line_num': start_line,
|
|
|
|
'column_num': start_column,
|
|
|
|
},
|
|
|
|
'end': {
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
'filepath': filepath,
|
2015-09-12 11:06:17 -04:00
|
|
|
'line_num': end_line,
|
|
|
|
'column_num': end_column,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
'replacement_text': replacement_text
|
|
|
|
}
|
2015-09-06 15:07:42 -04:00
|
|
|
|
|
|
|
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
@patch( 'vim.command', new_callable=ExtendedMock )
|
|
|
|
@patch( 'vim.current', new_callable=ExtendedMock)
|
2015-11-07 20:16:13 -05:00
|
|
|
def WriteToPreviewWindow_test( vim_current, vim_command ):
|
2015-09-06 15:07:42 -04:00
|
|
|
vim_current.window.options.__getitem__ = MagicMock( return_value = True )
|
|
|
|
|
|
|
|
vimsupport.WriteToPreviewWindow( "test" )
|
|
|
|
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
vim_command.assert_has_exact_calls( [
|
2015-09-06 15:07:42 -04:00
|
|
|
call( 'silent! pclose!' ),
|
|
|
|
call( 'silent! pedit! _TEMP_FILE_' ),
|
|
|
|
call( 'silent! wincmd P' ),
|
|
|
|
call( 'silent! wincmd p' ) ] )
|
|
|
|
|
|
|
|
vim_current.buffer.__setitem__.assert_called_with(
|
|
|
|
slice( None, None, None ), [ 'test' ] )
|
|
|
|
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
vim_current.buffer.options.__setitem__.assert_has_exact_calls( [
|
|
|
|
call( 'modifiable', True ),
|
|
|
|
call( 'readonly', False ),
|
2015-09-06 15:07:42 -04:00
|
|
|
call( 'buftype', 'nofile' ),
|
|
|
|
call( 'swapfile', False ),
|
|
|
|
call( 'modifiable', False ),
|
|
|
|
call( 'modified', False ),
|
|
|
|
call( 'readonly', True ),
|
|
|
|
], any_order = True )
|
|
|
|
|
|
|
|
|
|
|
|
@patch( 'vim.current' )
|
2015-11-07 20:16:13 -05:00
|
|
|
def WriteToPreviewWindow_MultiLine_test( vim_current ):
|
2015-09-06 15:07:42 -04:00
|
|
|
vim_current.window.options.__getitem__ = MagicMock( return_value = True )
|
|
|
|
vimsupport.WriteToPreviewWindow( "test\ntest2" )
|
|
|
|
|
|
|
|
vim_current.buffer.__setitem__.assert_called_with(
|
|
|
|
slice( None, None, None ), [ 'test', 'test2' ] )
|
|
|
|
|
|
|
|
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
@patch( 'vim.command', new_callable=ExtendedMock )
|
|
|
|
@patch( 'vim.current', new_callable=ExtendedMock )
|
2015-11-07 20:16:13 -05:00
|
|
|
def WriteToPreviewWindow_JumpFail_test( vim_current, vim_command ):
|
2015-09-06 15:07:42 -04:00
|
|
|
vim_current.window.options.__getitem__ = MagicMock( return_value = False )
|
|
|
|
|
|
|
|
vimsupport.WriteToPreviewWindow( "test" )
|
|
|
|
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
vim_command.assert_has_exact_calls( [
|
2015-09-06 15:07:42 -04:00
|
|
|
call( 'silent! pclose!' ),
|
|
|
|
call( 'silent! pedit! _TEMP_FILE_' ),
|
|
|
|
call( 'silent! wincmd P' ),
|
|
|
|
call( "echom 'test'" ),
|
|
|
|
] )
|
|
|
|
|
|
|
|
vim_current.buffer.__setitem__.assert_not_called()
|
|
|
|
vim_current.buffer.options.__setitem__.assert_not_called()
|
|
|
|
|
|
|
|
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
@patch( 'vim.command', new_callable=ExtendedMock )
|
|
|
|
@patch( 'vim.current', new_callable=ExtendedMock )
|
2015-11-07 20:16:13 -05:00
|
|
|
def WriteToPreviewWindow_JumpFail_MultiLine_test( vim_current, vim_command ):
|
2015-09-06 15:07:42 -04:00
|
|
|
|
|
|
|
vim_current.window.options.__getitem__ = MagicMock( return_value = False )
|
|
|
|
|
|
|
|
vimsupport.WriteToPreviewWindow( "test\ntest2" )
|
|
|
|
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
vim_command.assert_has_exact_calls( [
|
2015-09-06 15:07:42 -04:00
|
|
|
call( 'silent! pclose!' ),
|
|
|
|
call( 'silent! pedit! _TEMP_FILE_' ),
|
|
|
|
call( 'silent! wincmd P' ),
|
|
|
|
call( "echom 'test'" ),
|
|
|
|
call( "echom 'test2'" ),
|
|
|
|
] )
|
|
|
|
|
|
|
|
vim_current.buffer.__setitem__.assert_not_called()
|
|
|
|
vim_current.buffer.options.__setitem__.assert_not_called()
|
2015-11-07 20:16:13 -05:00
|
|
|
|
|
|
|
|
|
|
|
def CheckFilename_test():
|
|
|
|
assert_that(
|
|
|
|
calling( vimsupport.CheckFilename ).with_args( None ),
|
|
|
|
raises( RuntimeError, "'None' is not a valid filename" )
|
|
|
|
)
|
|
|
|
|
|
|
|
assert_that(
|
|
|
|
calling( vimsupport.CheckFilename ).with_args( 'nonexistent_file' ),
|
|
|
|
raises( RuntimeError,
|
|
|
|
"filename 'nonexistent_file' cannot be opened. "
|
2016-02-29 06:54:28 -05:00
|
|
|
"No such file or directory." )
|
2015-11-07 20:16:13 -05:00
|
|
|
)
|
|
|
|
|
|
|
|
assert_that( vimsupport.CheckFilename( __file__ ), none() )
|
|
|
|
|
|
|
|
|
2015-11-11 08:18:26 -05:00
|
|
|
def BufferIsVisibleForFilename_test():
|
|
|
|
buffers = [
|
|
|
|
{
|
|
|
|
'number': 1,
|
|
|
|
'filename': os.path.realpath( 'visible_filename' ),
|
|
|
|
'window': 1
|
|
|
|
},
|
|
|
|
{
|
|
|
|
'number': 2,
|
|
|
|
'filename': os.path.realpath( 'hidden_filename' ),
|
|
|
|
}
|
|
|
|
]
|
2015-11-07 20:16:13 -05:00
|
|
|
|
2015-11-11 08:18:26 -05:00
|
|
|
with patch( 'vim.buffers', buffers ):
|
|
|
|
eq_( vimsupport.BufferIsVisibleForFilename( 'visible_filename' ), True )
|
|
|
|
eq_( vimsupport.BufferIsVisibleForFilename( 'hidden_filename' ), False )
|
|
|
|
eq_( vimsupport.BufferIsVisibleForFilename( 'another_filename' ), False )
|
2015-11-07 20:16:13 -05:00
|
|
|
|
|
|
|
|
2016-02-27 19:12:24 -05:00
|
|
|
@patch( 'ycm.vimsupport.GetBufferNumberForFilename',
|
|
|
|
side_effect = [ 2, 5, -1 ] )
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
@patch( 'vim.command',
|
|
|
|
side_effect = MockVimCommand,
|
2016-02-27 19:12:24 -05:00
|
|
|
new_callable = ExtendedMock )
|
|
|
|
def CloseBuffersForFilename_test( vim_command, *args ):
|
|
|
|
vimsupport.CloseBuffersForFilename( 'some_filename' )
|
2015-11-07 20:16:13 -05:00
|
|
|
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
vim_command.assert_has_exact_calls( [
|
2015-11-07 20:16:13 -05:00
|
|
|
call( 'silent! bwipeout! 2' ),
|
|
|
|
call( 'silent! bwipeout! 5' )
|
|
|
|
], any_order = True )
|
|
|
|
|
|
|
|
|
2016-02-27 19:12:24 -05:00
|
|
|
@patch( 'vim.command', new_callable = ExtendedMock )
|
|
|
|
@patch( 'vim.current', new_callable = ExtendedMock )
|
2015-11-07 20:16:13 -05:00
|
|
|
def OpenFilename_test( vim_current, vim_command ):
|
|
|
|
# Options used to open a logfile
|
|
|
|
options = {
|
|
|
|
'size': vimsupport.GetIntValue( '&previewheight' ),
|
|
|
|
'fix': True,
|
|
|
|
'watch': True,
|
|
|
|
'position': 'end'
|
|
|
|
}
|
|
|
|
|
|
|
|
vimsupport.OpenFilename( __file__, options )
|
|
|
|
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
vim_command.assert_has_exact_calls( [
|
|
|
|
call( '12split {0}'.format( __file__ ) ),
|
2015-11-07 20:16:13 -05:00
|
|
|
call( "exec "
|
|
|
|
"'au BufEnter <buffer> :silent! checktime {0}'".format( __file__ ) ),
|
|
|
|
call( 'silent! normal G zz' ),
|
|
|
|
call( 'silent! wincmd p' )
|
|
|
|
] )
|
|
|
|
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
vim_current.buffer.options.__setitem__.assert_has_exact_calls( [
|
2015-11-07 20:16:13 -05:00
|
|
|
call( 'autoread', True ),
|
|
|
|
] )
|
|
|
|
|
Support FixIt commands across buffers
We simply apply the changes to each file in turn. The existing replacement
logic is unchanged, except that it now no longer implicitly assumes we are
talking about the current buffer.
If a buffer is not visible for the requested file name, we open it in
a horizontal split, make the edits, then hide the window. Because this
can cause UI flickering, and leave hidden, modified buffers around, we
issue a warning to the user stating the number of files for which we are
going to do this. We pop up the quickfix list at the end of applying
the edits to allow the user to see what we changed.
If the user opts to abort due to, say, the file being open in another
window, we simply raise an error and give up, as undoing the changes
is too complex to do programatically, but trivial to do manually in such
a rare case.
2016-01-11 17:19:33 -05:00
|
|
|
vim_current.window.options.__setitem__.assert_has_exact_calls( [
|
2015-11-07 20:16:13 -05:00
|
|
|
call( 'winfixheight', True )
|
|
|
|
] )
|
2016-02-28 17:42:18 -05:00
|
|
|
|
|
|
|
|
|
|
|
@patch( 'ycm.vimsupport.BufferModified', side_effect = [ True ] )
|
|
|
|
@patch( 'ycm.vimsupport.FiletypesForBuffer', side_effect = [ [ 'cpp' ] ] )
|
|
|
|
def GetUnsavedAndCurrentBufferData_EncodedUnicodeCharsInBuffers_test( *args ):
|
|
|
|
mock_buffer = MagicMock()
|
|
|
|
mock_buffer.name = os.path.realpath( 'filename' )
|
|
|
|
mock_buffer.number = 1
|
|
|
|
mock_buffer.__iter__.return_value = [ u'abc', ToBytes( u'fДa' ) ]
|
|
|
|
|
|
|
|
with patch( 'vim.buffers', [ mock_buffer ] ):
|
|
|
|
assert_that( vimsupport.GetUnsavedAndCurrentBufferData(),
|
|
|
|
has_entry( mock_buffer.name,
|
|
|
|
has_entry( u'contents', u'abc\nfДa\n' ) ) )
|
|
|
|
|
|
|
|
|
|
|
|
# NOTE: Vim returns byte offsets for columns, not actual character columns. This
|
|
|
|
# makes 'ДД' have 4 columns: column 0, column 2 and column 4.
|
|
|
|
@patch( 'vim.current.line', ToBytes( 'ДДaa' ) )
|
|
|
|
@patch( 'ycm.vimsupport.CurrentColumn', side_effect = [ 4 ] )
|
|
|
|
def TextBeforeCursor_EncodedUnicode_test( *args ):
|
|
|
|
eq_( vimsupport.TextBeforeCursor(), u'ДД' )
|
|
|
|
|
|
|
|
|
|
|
|
# NOTE: Vim returns byte offsets for columns, not actual character columns. This
|
|
|
|
# makes 'ДД' have 4 columns: column 0, column 2 and column 4.
|
|
|
|
@patch( 'vim.current.line', ToBytes( 'aaДД' ) )
|
|
|
|
@patch( 'ycm.vimsupport.CurrentColumn', side_effect = [ 2 ] )
|
|
|
|
def TextAfterCursor_EncodedUnicode_test( *args ):
|
|
|
|
eq_( vimsupport.TextAfterCursor(), u'ДД' )
|
|
|
|
|
|
|
|
|
|
|
|
@patch( 'vim.current.line', ToBytes( 'fДa' ) )
|
|
|
|
def CurrentLineContents_EncodedUnicode_test( *args ):
|
|
|
|
eq_( vimsupport.CurrentLineContents(), u'fДa' )
|
2016-03-05 13:16:08 -05:00
|
|
|
|
|
|
|
|
|
|
|
@patch( 'vim.eval', side_effect = lambda x: x )
|
|
|
|
def VimExpressionToPythonType_IntAsUnicode_test( *args ):
|
|
|
|
eq_( vimsupport.VimExpressionToPythonType( '123' ), 123 )
|
|
|
|
|
|
|
|
|
|
|
|
@patch( 'vim.eval', side_effect = lambda x: x )
|
|
|
|
def VimExpressionToPythonType_IntAsBytes_test( *args ):
|
|
|
|
eq_( vimsupport.VimExpressionToPythonType( ToBytes( '123' ) ), 123 )
|
|
|
|
|
|
|
|
|
|
|
|
@patch( 'vim.eval', side_effect = lambda x: x )
|
|
|
|
def VimExpressionToPythonType_StringAsUnicode_test( *args ):
|
|
|
|
eq_( vimsupport.VimExpressionToPythonType( 'foo' ), 'foo' )
|
|
|
|
|
|
|
|
|
|
|
|
@patch( 'vim.eval', side_effect = lambda x: x )
|
|
|
|
def VimExpressionToPythonType_StringAsBytes_test( *args ):
|
|
|
|
eq_( vimsupport.VimExpressionToPythonType( ToBytes( 'foo' ) ), 'foo' )
|
|
|
|
|
|
|
|
|
|
|
|
@patch( 'vim.eval', side_effect = lambda x: x )
|
|
|
|
def VimExpressionToPythonType_ListPassthrough_test( *args ):
|
|
|
|
eq_( vimsupport.VimExpressionToPythonType( [ 1, 2 ] ), [ 1, 2 ] )
|
|
|
|
|
|
|
|
|
|
|
|
@patch( 'vim.eval', side_effect = lambda x: x )
|
|
|
|
def VimExpressionToPythonType_ObjectPassthrough_test( *args ):
|
|
|
|
eq_( vimsupport.VimExpressionToPythonType( { 1: 2 } ), { 1: 2 } )
|
|
|
|
|
|
|
|
|
|
|
|
@patch( 'vim.eval', side_effect = lambda x: x )
|
|
|
|
def VimExpressionToPythonType_GeneratorPassthrough_test( *args ):
|
|
|
|
gen = ( x**2 for x in [ 1, 2, 3 ] )
|
|
|
|
eq_( vimsupport.VimExpressionToPythonType( gen ), gen )
|
2016-06-19 15:38:07 -04:00
|
|
|
|
|
|
|
|
|
|
|
@patch( 'vim.eval',
|
|
|
|
new_callable = ExtendedMock,
|
|
|
|
side_effect = [ None, 2, None ] )
|
|
|
|
def SelectFromList_LastItem_test( vim_eval ):
|
|
|
|
eq_( vimsupport.SelectFromList( 'test', [ 'a', 'b' ] ),
|
|
|
|
1 )
|
|
|
|
|
|
|
|
vim_eval.assert_has_exact_calls( [
|
|
|
|
call( 'inputsave()' ),
|
|
|
|
call( 'inputlist( ["test", "1: a", "2: b"] )' ),
|
|
|
|
call( 'inputrestore()' )
|
|
|
|
] )
|
|
|
|
|
|
|
|
|
|
|
|
@patch( 'vim.eval',
|
|
|
|
new_callable = ExtendedMock,
|
|
|
|
side_effect = [ None, 1, None ] )
|
|
|
|
def SelectFromList_FirstItem_test( vim_eval ):
|
|
|
|
eq_( vimsupport.SelectFromList( 'test', [ 'a', 'b' ] ),
|
|
|
|
0 )
|
|
|
|
|
|
|
|
vim_eval.assert_has_exact_calls( [
|
|
|
|
call( 'inputsave()' ),
|
|
|
|
call( 'inputlist( ["test", "1: a", "2: b"] )' ),
|
|
|
|
call( 'inputrestore()' )
|
|
|
|
] )
|
|
|
|
|
|
|
|
|
|
|
|
@patch( 'vim.eval', side_effect = [ None, 3, None ] )
|
|
|
|
def SelectFromList_OutOfRange_test( vim_eval ):
|
|
|
|
assert_that( calling( vimsupport.SelectFromList).with_args( 'test',
|
|
|
|
[ 'a', 'b' ] ),
|
|
|
|
raises( RuntimeError, vimsupport.NO_SELECTION_MADE_MSG ) )
|
|
|
|
|
|
|
|
|
|
|
|
@patch( 'vim.eval', side_effect = [ None, 0, None ] )
|
|
|
|
def SelectFromList_SelectPrompt_test( vim_eval ):
|
|
|
|
assert_that( calling( vimsupport.SelectFromList ).with_args( 'test',
|
|
|
|
[ 'a', 'b' ] ),
|
|
|
|
raises( RuntimeError, vimsupport.NO_SELECTION_MADE_MSG ) )
|
|
|
|
|
|
|
|
|
|
|
|
@patch( 'vim.eval', side_effect = [ None, -199, None ] )
|
|
|
|
def SelectFromList_Negative_test( vim_eval ):
|
|
|
|
assert_that( calling( vimsupport.SelectFromList ).with_args( 'test',
|
|
|
|
[ 'a', 'b' ] ),
|
|
|
|
raises( RuntimeError, vimsupport.NO_SELECTION_MADE_MSG ) )
|