Update matches for all windows

This commit is contained in:
micbou 2018-05-17 14:52:40 +02:00
parent c9ff217737
commit 115f360092
No known key found for this signature in database
GPG Key ID: C7E8FD1F3BDA1E05
11 changed files with 590 additions and 369 deletions

View File

@ -59,7 +59,7 @@ class DiagnosticInterface( object ):
def PopulateLocationList( self ):
# Do nothing if loc list is already populated by diag_interface
if not self._user_options[ 'always_populate_location_list' ]:
self._UpdateLocationList()
self._UpdateLocationLists()
return bool( self._diagnostics )
@ -77,7 +77,7 @@ class DiagnosticInterface( object ):
self.UpdateMatches()
if self._user_options[ 'always_populate_location_list' ]:
self._UpdateLocationList()
self._UpdateLocationLists()
def _ApplyDiagnosticFilter( self, diags ):
@ -119,8 +119,8 @@ class DiagnosticInterface( object ):
return count
def _UpdateLocationList( self ):
vimsupport.SetLocationListForBuffer(
def _UpdateLocationLists( self ):
vimsupport.SetLocationListsForBuffer(
self._bufnr,
vimsupport.ConvertDiagnosticsToQfList( self._diagnostics ) )
@ -129,37 +129,19 @@ class DiagnosticInterface( object ):
if not self._user_options[ 'enable_diagnostic_highlighting' ]:
return
with vimsupport.CurrentWindow():
for window in vimsupport.GetWindowsForBufferNumber( self._bufnr ):
vimsupport.SwitchWindow( window )
matches_to_remove = vimsupport.GetDiagnosticMatchesInCurrentWindow()
for diags in itervalues( self._line_to_diags ):
# Insert squiggles in reverse order so that errors overlap warnings.
for diag in reversed( diags ):
patterns = []
group = ( 'YcmErrorSection' if _DiagnosticIsError( diag ) else
'YcmWarningSection' )
location_extent = diag[ 'location_extent' ]
if location_extent[ 'start' ][ 'line_num' ] <= 0:
location = diag[ 'location' ]
patterns.append( vimsupport.GetDiagnosticMatchPattern(
location[ 'line_num' ],
location[ 'column_num' ] ) )
else:
patterns.append( vimsupport.GetDiagnosticMatchPattern(
location_extent[ 'start' ][ 'line_num' ],
location_extent[ 'start' ][ 'column_num' ],
location_extent[ 'end' ][ 'line_num' ],
location_extent[ 'end' ][ 'column_num' ] ) )
for diag_range in diag[ 'ranges' ]:
patterns.append( vimsupport.GetDiagnosticMatchPattern(
diag_range[ 'start' ][ 'line_num' ],
diag_range[ 'start' ][ 'column_num' ],
diag_range[ 'end' ][ 'line_num' ],
diag_range[ 'end' ][ 'column_num' ] ) )
for pattern in patterns:
for pattern in _ConvertDiagnosticToMatchPatterns( diag ):
# The id doesn't matter for matches that we may add.
match = vimsupport.DiagnosticMatch( 0, group, pattern )
try:
@ -221,3 +203,29 @@ def _NormalizeDiagnostic( diag ):
location[ 'column_num' ] = ClampToOne( location[ 'column_num' ] )
location[ 'line_num' ] = ClampToOne( location[ 'line_num' ] )
return diag
def _ConvertDiagnosticToMatchPatterns( diagnostic ):
patterns = []
location_extent = diagnostic[ 'location_extent' ]
if location_extent[ 'start' ][ 'line_num' ] <= 0:
location = diagnostic[ 'location' ]
patterns.append( vimsupport.GetDiagnosticMatchPattern(
location[ 'line_num' ],
location[ 'column_num' ] ) )
else:
patterns.append( vimsupport.GetDiagnosticMatchPattern(
location_extent[ 'start' ][ 'line_num' ],
location_extent[ 'start' ][ 'column_num' ],
location_extent[ 'end' ][ 'line_num' ],
location_extent[ 'end' ][ 'column_num' ] ) )
for diagnostic_range in diagnostic[ 'ranges' ]:
patterns.append( vimsupport.GetDiagnosticMatchPattern(
diagnostic_range[ 'start' ][ 'line_num' ],
diagnostic_range[ 'start' ][ 'column_num' ],
diagnostic_range[ 'end' ][ 'line_num' ],
diagnostic_range[ 'end' ][ 'column_num' ] ) )
return patterns

View File

@ -34,7 +34,7 @@ from ycm.client.base_request import BuildRequestData
return_value = '/some/dir' )
def BuildRequestData_AddWorkingDir_test( *args ):
current_buffer = VimBuffer( 'foo' )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 1 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
assert_that( BuildRequestData(), has_entry( 'working_dir', '/some/dir' ) )
@ -42,6 +42,6 @@ def BuildRequestData_AddWorkingDir_test( *args ):
return_value = '/some/dir' )
def BuildRequestData_AddWorkingDirWithFileName_test( *args ):
current_buffer = VimBuffer( 'foo' )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 1 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
assert_that( BuildRequestData( current_buffer.number ),
has_entry( 'working_dir', '/some/dir' ) )

View File

@ -34,7 +34,7 @@ from ycm.tests import YouCompleteMeInstance
@YouCompleteMeInstance( { 'g:ycm_extra_conf_vim_data': [ 'tempname()' ] } )
def SendCommandRequest_ExtraConfVimData_Works_test( ycm ):
current_buffer = VimBuffer( 'buffer' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with patch( 'ycm.youcompleteme.SendCommandRequest' ) as send_request:
ycm.SendCommandRequest( [ 'GoTo' ], 'python', False, 1, 1 )
assert_that(
@ -59,7 +59,7 @@ def SendCommandRequest_ExtraConfVimData_Works_test( ycm ):
@YouCompleteMeInstance( { 'g:ycm_extra_conf_vim_data': [ 'undefined_value' ] } )
def SendCommandRequest_ExtraConfData_UndefinedValue_test( ycm ):
current_buffer = VimBuffer( 'buffer' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with patch( 'ycm.youcompleteme.SendCommandRequest' ) as send_request:
ycm.SendCommandRequest( [ 'GoTo' ], 'python', False, 1, 1 )
assert_that(
@ -82,7 +82,7 @@ def SendCommandRequest_ExtraConfData_UndefinedValue_test( ycm ):
def SendCommandRequest_BuildRange_NoVisualMarks_test( ycm, *args ):
current_buffer = VimBuffer( 'buffer', contents = [ 'first line',
'second line' ] )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with patch( 'ycm.youcompleteme.SendCommandRequest' ) as send_request:
ycm.SendCommandRequest( [ 'GoTo' ], 'python', True, 1, 2 )
send_request.assert_called_once_with(
@ -114,7 +114,7 @@ def SendCommandRequest_BuildRange_VisualMarks_test( ycm, *args ):
'second line' ],
visual_start = [ 1, 4 ],
visual_end = [ 2, 8 ] )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with patch( 'ycm.youcompleteme.SendCommandRequest' ) as send_request:
ycm.SendCommandRequest( [ 'GoTo' ], 'python', True, 1, 2 )
send_request.assert_called_once_with(

View File

@ -66,7 +66,7 @@ def SendCompletionRequest_UnicodeWorkingDirectory_test( ycm ):
return { 'completions': [], 'completion_start_column': 1 }
with CurrentWorkingDirectory( unicode_dir ):
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with MockCompletionRequest( ServerResponse ):
ycm.SendCompletionRequest()
ok_( ycm.CompletionRequestReady() )
@ -106,7 +106,7 @@ def SendCompletionRequest_ResponseContainingError_test( ycm, post_vim_message ):
} ]
}
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with MockCompletionRequest( ServerResponse ):
ycm.SendCompletionRequest()
ok_( ycm.CompletionRequestReady() )
@ -138,7 +138,7 @@ def SendCompletionRequest_ErrorFromServer_test( ycm,
post_vim_message,
logger ):
current_buffer = VimBuffer( 'buffer' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with MockCompletionRequest( ServerError( 'Server error' ) ):
ycm.SendCompletionRequest()
ok_( ycm.CompletionRequestReady() )

View File

@ -57,10 +57,9 @@ def MockArbitraryBuffer( filetype ):
# Arbitrary, but valid, single buffer open.
current_buffer = VimBuffer( os.path.realpath( 'TEST_BUFFER' ),
window = 1,
filetype = filetype )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
yield
@ -402,7 +401,7 @@ def EventNotification_FileReadyToParse_TagFiles_UnicodeWorkingDirectory_test(
with patch( 'ycm.client.event_notification.EventNotification.'
'PostDataToHandlerAsync' ) as post_data_to_handler_async:
with CurrentWorkingDirectory( unicode_dir ):
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 5 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 5 ) ):
ycm.OnFileReadyToParse()
assert_that(
@ -455,7 +454,7 @@ def EventNotification_BufferVisit_BuildRequestForCurrentAndUnsavedBuffers_test(
with patch( 'ycm.client.event_notification.EventNotification.'
'PostDataToHandlerAsync' ) as post_data_to_handler_async:
with MockVimBuffers( [ current_buffer, modified_buffer, unmodified_buffer ],
current_buffer,
[ current_buffer ],
( 1, 5 ) ):
ycm.OnBufferVisit()
@ -503,7 +502,8 @@ def EventNotification_BufferUnload_BuildRequestForDeletedAndUnsavedBuffers_test(
with patch( 'ycm.client.event_notification.EventNotification.'
'PostDataToHandlerAsync' ) as post_data_to_handler_async:
with MockVimBuffers( [ current_buffer, deleted_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer, deleted_buffer ],
[ current_buffer ] ):
ycm.OnBufferUnload( deleted_buffer.number )
assert_that(
@ -543,7 +543,7 @@ def EventNotification_FileReadyToParse_SyntaxKeywords_SeedWithCache_test(
with patch( 'ycm.client.event_notification.EventNotification.'
'PostDataToHandlerAsync' ) as post_data_to_handler_async:
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
ycm.OnFileReadyToParse()
assert_that(
# Positional arguments passed to PostDataToHandlerAsync.
@ -578,7 +578,7 @@ def EventNotification_FileReadyToParse_SyntaxKeywords_ClearCacheIfRestart_test(
with patch( 'ycm.client.event_notification.EventNotification.'
'PostDataToHandlerAsync' ) as post_data_to_handler_async:
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
ycm.OnFileReadyToParse()
assert_that(
# Positional arguments passed to PostDataToHandlerAsync.

View File

@ -52,7 +52,7 @@ def OmniCompleter_GetCompletions_Cache_List_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 5 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 5 ) ):
ycm.SendCompletionRequest()
assert_that(
ycm.GetCompletionResponse(),
@ -76,7 +76,7 @@ def OmniCompleter_GetCompletions_Cache_ListFilter_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 6 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 6 ) ):
ycm.SendCompletionRequest()
assert_that(
ycm.GetCompletionResponse(),
@ -100,7 +100,7 @@ def OmniCompleter_GetCompletions_NoCache_List_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 5 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 5 ) ):
ycm.SendCompletionRequest()
assert_that(
ycm.GetCompletionResponse(),
@ -124,7 +124,7 @@ def OmniCompleter_GetCompletions_NoCache_ListFilter_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 6 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 6 ) ):
ycm.SendCompletionRequest()
# Actual result is that the results are not filtered, as we expect the
# omnifunc or vim itself to do this filtering.
@ -150,7 +150,7 @@ def OmniCompleter_GetCompletions_NoCache_UseFindStart_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 6 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 6 ) ):
ycm.SendCompletionRequest()
# Actual result is that the results are not filtered, as we expect the
# omnifunc or vim itself to do this filtering.
@ -176,7 +176,7 @@ def OmniCompleter_GetCompletions_Cache_UseFindStart_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 6 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 6 ) ):
ycm.SendCompletionRequest()
# There are no results because the query 'test.t' doesn't match any
# candidate (and cache_omnifunc=1, so we FilterAndSortCandidates).
@ -202,7 +202,7 @@ def OmniCompleter_GetCompletions_Cache_Object_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 6 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 6 ) ):
ycm.SendCompletionRequest()
assert_that(
ycm.GetCompletionResponse(),
@ -241,7 +241,7 @@ def OmniCompleter_GetCompletions_Cache_ObjectList_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 7 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 7 ) ):
ycm.SendCompletionRequest()
assert_that(
ycm.GetCompletionResponse(),
@ -286,7 +286,7 @@ def OmniCompleter_GetCompletions_NoCache_ObjectList_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 7 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 7 ) ):
ycm.SendCompletionRequest()
# We don't filter the result - we expect the omnifunc to do that
# based on the query we supplied (Note: that means no fuzzy matching!).
@ -339,7 +339,7 @@ def OmniCompleter_GetCompletions_Cache_ObjectListObject_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 7 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 7 ) ):
ycm.SendCompletionRequest()
assert_that(
ycm.GetCompletionResponse(),
@ -384,7 +384,7 @@ def OmniCompleter_GetCompletions_NoCache_ObjectListObject_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 7 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 7 ) ):
ycm.SendCompletionRequest()
# No FilterAndSortCandidates for cache_omnifunc=0 (we expect the omnifunc
# to do the filtering?)
@ -422,7 +422,7 @@ def OmniCompleter_GetCompletions_Cache_List_Unicode_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 12 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 12 ) ):
ycm.SendCompletionRequest()
assert_that(
ycm.GetCompletionResponse(),
@ -448,7 +448,7 @@ def OmniCompleter_GetCompletions_NoCache_List_Unicode_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 12 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 12 ) ):
ycm.SendCompletionRequest()
assert_that(
ycm.GetCompletionResponse(),
@ -474,7 +474,7 @@ def OmniCompleter_GetCompletions_Cache_List_Filter_Unicode_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 17 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 17 ) ):
ycm.SendCompletionRequest()
assert_that(
ycm.GetCompletionResponse(),
@ -498,7 +498,7 @@ def OmniCompleter_GetCompletions_NoCache_List_Filter_Unicode_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 17 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 17 ) ):
ycm.SendCompletionRequest()
assert_that(
ycm.GetCompletionResponse(),
@ -537,7 +537,7 @@ def OmniCompleter_GetCompletions_Cache_ObjectList_Unicode_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 17 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 17 ) ):
ycm.SendCompletionRequest()
assert_that(
ycm.GetCompletionResponse(),
@ -591,7 +591,7 @@ def OmniCompleter_GetCompletions_Cache_ObjectListObject_Unicode_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 13 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 13 ) ):
ycm.SendCompletionRequest()
assert_that(
ycm.GetCompletionResponse(),
@ -634,7 +634,7 @@ def OmniCompleter_GetCompletions_RestoreCursorPositionAfterOmnifuncCall_test(
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 3, 5 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 3, 5 ) ):
ycm.SendCompletionRequest()
assert_that(
vimsupport.CurrentLineAndColumn(),
@ -662,7 +662,7 @@ def OmniCompleter_GetCompletions_NoCache_NoSemanticTrigger_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 3 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 3 ) ):
ycm.SendCompletionRequest()
assert_that(
ycm.GetCompletionResponse(),
@ -686,7 +686,7 @@ def OmniCompleter_GetCompletions_NoCache_ForceSemantic_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 3 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 3 ) ):
ycm.SendCompletionRequest( force_semantic = True )
assert_that(
ycm.GetCompletionResponse(),
@ -712,7 +712,7 @@ def OmniCompleter_GetCompletions_FiletypeDisabled_SemanticTrigger_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 6 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 6 ) ):
ycm.SendCompletionRequest()
assert_that(
ycm.GetCompletionResponse(),
@ -740,7 +740,7 @@ def OmniCompleter_GetCompletions_AllFiletypesDisabled_SemanticTrigger_test(
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 6 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 6 ) ):
ycm.SendCompletionRequest()
assert_that(
ycm.GetCompletionResponse(),
@ -766,7 +766,7 @@ def OmniCompleter_GetCompletions_FiletypeDisabled_ForceSemantic_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 6 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 6 ) ):
ycm.SendCompletionRequest( force_semantic = True )
assert_that(
ycm.GetCompletionResponse(),
@ -792,7 +792,7 @@ def OmniCompleter_GetCompletions_AllFiletypesDisabled_ForceSemantic_test( ycm ):
filetype = FILETYPE,
omnifunc = Omnifunc )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 6 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 6 ) ):
ycm.SendCompletionRequest( force_semantic = True )
assert_that(
ycm.GetCompletionResponse(),

View File

@ -22,6 +22,7 @@ from __future__ import absolute_import
# Not installing aliases from python-future; it's unreliable and slow.
from builtins import * # noqa
from collections import defaultdict
from future.utils import iteritems, PY2
from mock import DEFAULT, MagicMock, patch
from hamcrest import assert_that, equal_to
@ -70,7 +71,7 @@ LET_REGEX = re.compile( '^let (?P<option>[\w:]+) = (?P<value>.*)$' )
# https://github.com/Valloric/YouCompleteMe/pull/1694
VIM_MOCK = MagicMock()
VIM_MATCHES = []
VIM_MATCHES_FOR_WINDOW = defaultdict( list )
VIM_SIGNS = []
VIM_OPTIONS = {
@ -107,9 +108,9 @@ def _MockGetBufferNumber( buffer_filename ):
def _MockGetBufferWindowNumber( buffer_number ):
for vim_buffer in VIM_MOCK.buffers:
if vim_buffer.number == buffer_number and vim_buffer.window:
return vim_buffer.window
for window in VIM_MOCK.windows:
if window.buffer.number == buffer_number:
return window.number
return -1
@ -198,25 +199,26 @@ def _MockVimFunctionsEval( value ):
def _MockVimMatchEval( value ):
current_window = VIM_MOCK.current.window.number
if value == 'getmatches()':
# Returning a copy, because ClearYcmSyntaxMatches() gets the result of
# getmatches(), iterates over it and removes elements from VIM_MATCHES.
return list( VIM_MATCHES )
return VIM_MATCHES_FOR_WINDOW[ current_window ]
match = MATCHADD_REGEX.search( value )
if match:
group = match.group( 'group' )
option = match.group( 'pattern' )
vim_match = VimMatch( group, option )
VIM_MATCHES.append( vim_match )
VIM_MATCHES_FOR_WINDOW[ current_window ].append( vim_match )
return vim_match.id
match = MATCHDELETE_REGEX.search( value )
if match:
match_id = int( match.group( 'id' ) )
for index, vim_match in enumerate( VIM_MATCHES ):
vim_matches = VIM_MATCHES_FOR_WINDOW[ current_window ]
for index, vim_match in enumerate( vim_matches ):
if vim_match.id == match_id:
VIM_MATCHES.pop( index )
vim_matches.pop( index )
return -1
return 0
@ -334,7 +336,6 @@ class VimBuffer( object ):
- |filetype| : buffer filetype. Empty string if no filetype is set;
- |modified| : True if the buffer has unsaved changes, False otherwise;
- |bufhidden|: value of the 'bufhidden' option (see :h bufhidden);
- |window| : number of the buffer window. None if the buffer is hidden;
- |omnifunc| : omni completion function used by the buffer. Must be a Python
function that takes the same arguments and returns the same
values as a Vim completion function (:h complete-functions).
@ -351,7 +352,6 @@ class VimBuffer( object ):
filetype = '',
modified = False,
bufhidden = '',
window = None,
omnifunc = None,
visual_start = None,
visual_end = None ):
@ -361,7 +361,6 @@ class VimBuffer( object ):
self.filetype = filetype
self.modified = modified
self.bufhidden = bufhidden
self.window = window
self.omnifunc = omnifunc
self.omnifunc_name = omnifunc.__name__ if omnifunc else ''
self.changedtick = 1
@ -402,9 +401,9 @@ class VimBuffer( object ):
class VimBuffers( object ):
"""An object that looks like a vim.buffers object."""
def __init__( self, *buffers ):
"""Arguments are VimBuffer objects."""
self._buffers = list( buffers )
def __init__( self, buffers ):
"""|buffers| is a list of VimBuffer objects."""
self._buffers = buffers
def __getitem__( self, number ):
@ -424,10 +423,61 @@ class VimBuffers( object ):
return self._buffers.pop( index )
class VimWindow( object ):
"""An object that looks like a vim.window object:
- |number|: number of the window;
- |buffer_object|: a VimBuffer object representing the buffer inside the
window;
- |cursor|: a tuple corresponding to the cursor position."""
def __init__( self, number, buffer_object, cursor = None ):
self.number = number
self.buffer = buffer_object
self.cursor = cursor
class VimWindows( object ):
"""An object that looks like a vim.windows object."""
def __init__( self, buffers, cursor ):
"""|buffers| is a list of VimBuffer objects corresponding to the window
layout. The first element of that list is assumed to be the current window.
|cursor| is the cursor position of that window."""
windows = []
windows.append( VimWindow( 1, buffers[ 0 ], cursor ) )
for window_number in range( 1, len( buffers ) ):
windows.append( VimWindow( window_number + 1, buffers[ window_number ] ) )
self._windows = windows
def __getitem__( self, number ):
"""Emulates vim.windows[ number ]"""
for window in self._windows:
if number == window.number:
return window
raise KeyError( number )
def __iter__( self ):
"""Emulates for loop on vim.windows"""
return iter( self._windows )
class VimCurrent( object ):
"""An object that looks like a vim.current object. |current_window| must be a
VimWindow object."""
def __init__( self, current_window ):
self.buffer = current_window.buffer
self.window = current_window
self.line = self.buffer.contents[ current_window.cursor[ 0 ] - 1 ]
class VimMatch( object ):
def __init__( self, group, pattern ):
self.id = len( VIM_MATCHES ) + 1
current_window = VIM_MOCK.current.window.number
self.id = len( VIM_MATCHES_FOR_WINDOW[ current_window ] ) + 1
self.group = group
self.pattern = pattern
@ -480,19 +530,25 @@ class VimSign( object ):
@contextlib.contextmanager
def MockVimBuffers( buffers, current_buffer, cursor_position = ( 1, 1 ) ):
def MockVimBuffers( buffers, window_buffers, cursor_position = ( 1, 1 ) ):
"""Simulates the Vim buffers list |buffers| where |current_buffer| is the
buffer displayed in the current window and |cursor_position| is the current
cursor position. All buffers are represented by a VimBuffer object."""
if current_buffer not in buffers:
raise RuntimeError( 'Current buffer must be part of the buffers list.' )
if ( not isinstance( buffers, list ) or
not all( isinstance( buf, VimBuffer ) for buf in buffers ) ):
raise RuntimeError( 'First parameter must be a list of VimBuffer objects.' )
if ( not isinstance( window_buffers, list ) or
not all( isinstance( buf, VimBuffer ) for buf in window_buffers ) ):
raise RuntimeError( 'Second parameter must be a list of VimBuffer objects '
'representing the window layout.' )
if len( window_buffers ) < 1:
raise RuntimeError( 'Second parameter must contain at least one element '
'which corresponds to the current window.' )
line = current_buffer.contents[ cursor_position[ 0 ] - 1 ]
with patch( 'vim.buffers', VimBuffers( *buffers ) ):
with patch( 'vim.current.buffer', current_buffer ):
with patch( 'vim.current.window.cursor', cursor_position ):
with patch( 'vim.current.line', line ):
with patch( 'vim.buffers', VimBuffers( buffers ) ):
with patch( 'vim.windows', VimWindows( window_buffers,
cursor_position ) ) as windows:
with patch( 'vim.current', VimCurrent( windows[ 1 ] ) ):
yield VIM_MOCK
@ -518,7 +574,6 @@ def MockVimModule():
Failure to use this approach may lead to unexpected failures in other
tests."""
VIM_MOCK.buffers = {}
VIM_MOCK.command = MagicMock( side_effect = _MockVimCommand )
VIM_MOCK.eval = MagicMock( side_effect = _MockVimEval )
VIM_MOCK.error = VimError

View File

@ -41,7 +41,7 @@ import json
@patch( 'vim.eval', new_callable = ExtendedMock )
def SetLocationListForBuffer_Current_test( vim_eval ):
def SetLocationListsForBuffer_Current_test( vim_eval ):
diagnostics = [ {
'bufnr': 3,
'filename': 'some_filename',
@ -50,18 +50,17 @@ def SetLocationListForBuffer_Current_test( vim_eval ):
'type': 'E',
'valid': 1
} ]
current_buffer = VimBuffer( '/test', number = 3, window = 7 )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 1 ) ):
vimsupport.SetLocationListForBuffer( 3, diagnostics )
current_buffer = VimBuffer( '/test', number = 3 )
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
vimsupport.SetLocationListsForBuffer( 3, diagnostics )
# We asked for the buffer which is current, so we use winnr 0
vim_eval.assert_has_exact_calls( [
call( 'setloclist( 0, {0} )'.format( json.dumps( diagnostics ) ) )
call( 'setloclist( 1, {0} )'.format( json.dumps( diagnostics ) ) )
] )
@patch( 'vim.eval', new_callable = ExtendedMock, side_effect = [ 8, 1 ] )
def SetLocationListForBuffer_NotCurrent_test( vim_eval ):
@patch( 'vim.eval', new_callable = ExtendedMock )
def SetLocationListsForBuffer_NotCurrent_test( vim_eval ):
diagnostics = [ {
'bufnr': 3,
'filename': 'some_filename',
@ -70,22 +69,16 @@ def SetLocationListForBuffer_NotCurrent_test( vim_eval ):
'type': 'E',
'valid': 1
} ]
current_buffer = VimBuffer( '/test', number = 3, window = 7 )
other_buffer = VimBuffer( '/notcurrent', number = 1, window = 8 )
with MockVimBuffers( [ current_buffer, other_buffer ],
current_buffer,
( 1, 1 ) ):
vimsupport.SetLocationListForBuffer( 1, diagnostics )
current_buffer = VimBuffer( '/test', number = 3 )
other_buffer = VimBuffer( '/notcurrent', number = 1 )
with MockVimBuffers( [ current_buffer, other_buffer ], [ current_buffer ] ):
vimsupport.SetLocationListsForBuffer( 1, diagnostics )
# We asked for a buffer which is not current, so we find the window
vim_eval.assert_has_exact_calls( [
call( 'bufwinnr(1)' ), # returns 8 due to side_effect
call( 'setloclist( 8, {0} )'.format( json.dumps( diagnostics ) ) )
] )
vim_eval.assert_not_called()
@patch( 'vim.eval', new_callable = ExtendedMock, side_effect = [ -1, 1 ] )
def SetLocationListForBuffer_NotVisible_test( vim_eval ):
def SetLocationListsForBuffer_NotVisible_test( vim_eval ):
diagnostics = [ {
'bufnr': 3,
'filename': 'some_filename',
@ -94,17 +87,32 @@ def SetLocationListForBuffer_NotVisible_test( vim_eval ):
'type': 'E',
'valid': 1
} ]
current_buffer = VimBuffer( '/test', number = 3, window = 7 )
other_buffer = VimBuffer( '/notcurrent', number = 1, window = 8 )
with MockVimBuffers( [ current_buffer, other_buffer ],
current_buffer,
( 1, 1 ) ):
vimsupport.SetLocationListForBuffer( 1, diagnostics )
current_buffer = VimBuffer( '/test', number = 3 )
other_buffer = VimBuffer( '/notcurrent', number = 1 )
with MockVimBuffers( [ current_buffer, other_buffer ], [ current_buffer ] ):
vimsupport.SetLocationListsForBuffer( 1, diagnostics )
vim_eval.assert_not_called()
@patch( 'vim.eval', new_callable = ExtendedMock, side_effect = [ -1, 1 ] )
def SetLocationListsForBuffer_MultipleWindows_test( vim_eval ):
diagnostics = [ {
'bufnr': 3,
'filename': 'some_filename',
'lnum': 5,
'col': 22,
'type': 'E',
'valid': 1
} ]
current_buffer = VimBuffer( '/test', number = 3 )
other_buffer = VimBuffer( '/notcurrent', number = 1 )
with MockVimBuffers( [ current_buffer, other_buffer ],
[ current_buffer, other_buffer ] ):
vimsupport.SetLocationListsForBuffer( 1, diagnostics )
# We asked for a buffer which is not current, so we find the window
vim_eval.assert_has_exact_calls( [
call( 'bufwinnr(1)' ), # returns -1 due to side_effect
call( 'setloclist( 0, {0} )'.format( json.dumps( diagnostics ) ) )
call( 'setloclist( 2, {0} )'.format( json.dumps( diagnostics ) ) )
] )
@ -118,8 +126,8 @@ def SetLocationList_test( vim_eval ):
'type': 'E',
'valid': 1
} ]
current_buffer = VimBuffer( '/test', number = 3, window = 7 )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 1 ) ):
current_buffer = VimBuffer( '/test', number = 3 )
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 1 ) ):
vimsupport.SetLocationList( diagnostics )
vim_eval.assert_has_calls( [
@ -137,10 +145,10 @@ def SetLocationList_NotCurrent_test( vim_eval ):
'type': 'E',
'valid': 1
} ]
current_buffer = VimBuffer( '/test', number = 3, window = 7 )
other_buffer = VimBuffer( '/notcurrent', number = 1, window = 8 )
current_buffer = VimBuffer( '/test', number = 3 )
other_buffer = VimBuffer( '/notcurrent', number = 1 )
with MockVimBuffers( [ current_buffer, other_buffer ],
current_buffer,
[ current_buffer, other_buffer ],
( 1, 1 ) ):
vimsupport.SetLocationList( diagnostics )
@ -171,7 +179,7 @@ def SetFittingHeightForCurrentWindow_test( vim_command, *args ):
# Create a buffer with one line that is longer than the window width.
current_buffer = VimBuffer( 'buffer',
contents = [ 'a' * 140 ] )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
vimsupport.SetFittingHeightForCurrentWindow()
vim_command.assert_called_once_with( '2wincmd _' )
@ -1373,24 +1381,21 @@ def WriteToPreviewWindow_JumpFail_MultiLine_test( vim_current, vim_command ):
def BufferIsVisibleForFilename_test():
vim_buffers = [
VimBuffer( 'visible_filename', number = 1, window = 1 ),
VimBuffer( 'hidden_filename', number = 2, window = None )
]
visible_buffer = VimBuffer( 'visible_filename', number = 1 )
hidden_buffer = VimBuffer( 'hidden_filename', number = 2 )
with patch( 'vim.buffers', vim_buffers ):
with MockVimBuffers( [ visible_buffer, hidden_buffer ], [ visible_buffer ] ):
eq_( vimsupport.BufferIsVisibleForFilename( 'visible_filename' ), True )
eq_( vimsupport.BufferIsVisibleForFilename( 'hidden_filename' ), False )
eq_( vimsupport.BufferIsVisibleForFilename( 'another_filename' ), False )
def CloseBuffersForFilename_test():
vim_buffers = [
VimBuffer( 'some_filename', number = 2 ),
VimBuffer( 'some_filename', number = 5 )
]
current_buffer = VimBuffer( 'some_filename', number = 2 )
other_buffer = VimBuffer( 'some_filename', number = 5 )
with MockVimBuffers( vim_buffers, vim_buffers[ 0 ] ) as vim:
with MockVimBuffers( [ current_buffer, other_buffer ],
[ current_buffer ] ) as vim:
vimsupport.CloseBuffersForFilename( 'some_filename' )
assert_that( vim.buffers, empty() )
@ -1555,7 +1560,7 @@ def SelectFromList_Negative_test( vim_eval ):
def Filetypes_IntegerFiletype_test():
current_buffer = VimBuffer( 'buffer', number = 1, filetype = '42' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
assert_that( vimsupport.CurrentFiletypes(), contains( '42' ) )
assert_that( vimsupport.GetBufferFiletypes( 1 ), contains( '42' ) )
assert_that( vimsupport.FiletypesForBuffer( current_buffer ),
@ -1613,7 +1618,7 @@ def JumpToLocation_SameFile_SameBuffer_NoSwapFile_test( vim_command ):
# No 'u' prefix for the current buffer name string to simulate Vim returning
# bytes on Python 2 but unicode on Python 3.
current_buffer = VimBuffer( 'uni¢𐍈d€' )
with MockVimBuffers( [ current_buffer ], current_buffer ) as vim:
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ) as vim:
vimsupport.JumpToLocation( os.path.realpath( u'uni¢𐍈d€' ), 2, 5 )
assert_that( vim.current.window.cursor, equal_to( ( 2, 4 ) ) )
@ -1628,7 +1633,7 @@ def JumpToLocation_SameFile_SameBuffer_NoSwapFile_test( vim_command ):
@patch( 'vim.command', new_callable = ExtendedMock )
def JumpToLocation_DifferentFile_SameBuffer_Unmodified_test( vim_command ):
current_buffer = VimBuffer( 'uni¢𐍈d€' )
with MockVimBuffers( [ current_buffer ], current_buffer ) as vim:
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ) as vim:
target_name = os.path.realpath( u'different_uni¢𐍈d€' )
vimsupport.JumpToLocation( target_name, 2, 5 )
@ -1648,7 +1653,7 @@ def JumpToLocation_DifferentFile_SameBuffer_Modified_CannotHide_test(
vim_command ):
current_buffer = VimBuffer( 'uni¢𐍈d€', modified = True )
with MockVimBuffers( [ current_buffer ], current_buffer ) as vim:
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ) as vim:
target_name = os.path.realpath( u'different_uni¢𐍈d€' )
vimsupport.JumpToLocation( target_name, 2, 5 )
@ -1668,7 +1673,7 @@ def JumpToLocation_DifferentFile_SameBuffer_Modified_CanHide_test(
vim_command ):
current_buffer = VimBuffer( 'uni¢𐍈d€', modified = True, bufhidden = "hide" )
with MockVimBuffers( [ current_buffer ], current_buffer ) as vim:
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ) as vim:
target_name = os.path.realpath( u'different_uni¢𐍈d€' )
vimsupport.JumpToLocation( target_name, 2, 5 )
@ -1689,7 +1694,7 @@ def JumpToLocation_DifferentFile_SameBuffer_SwapFile_Unexpected_test(
vim_command ):
current_buffer = VimBuffer( 'uni¢𐍈d€' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
assert_that(
calling( vimsupport.JumpToLocation ).with_args(
os.path.realpath( u'different_uni¢𐍈d€' ), 2, 5 ),
@ -1704,7 +1709,7 @@ def JumpToLocation_DifferentFile_SameBuffer_SwapFile_Unexpected_test(
side_effect = [ None, VimError( 'E325' ), None ] )
def JumpToLocation_DifferentFile_SameBuffer_SwapFile_Quit_test( vim_command ):
current_buffer = VimBuffer( 'uni¢𐍈d€' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
target_name = os.path.realpath( u'different_uni¢𐍈d€' )
vimsupport.JumpToLocation( target_name, 2, 5 )
@ -1722,7 +1727,7 @@ def JumpToLocation_DifferentFile_SameBuffer_SwapFile_Quit_test( vim_command ):
side_effect = [ None, KeyboardInterrupt, None ] )
def JumpToLocation_DifferentFile_SameBuffer_SwapFile_Abort_test( vim_command ):
current_buffer = VimBuffer( 'uni¢𐍈d€' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
target_name = os.path.realpath( u'different_uni¢𐍈d€' )
vimsupport.JumpToLocation( target_name, 2, 5 )
@ -1740,7 +1745,7 @@ def JumpToLocation_DifferentFile_NewOrExistingTab_NotAlreadyOpened_test(
vim_command ):
current_buffer = VimBuffer( 'uni¢𐍈d€' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
target_name = os.path.realpath( u'different_uni¢𐍈d€' )
vimsupport.JumpToLocation( target_name, 2, 5 )
@ -1765,7 +1770,7 @@ def JumpToLocation_DifferentFile_NewOrExistingTab_AlreadyOpened_test(
current_tab = MagicMock( windows = [ current_window, different_window ] )
with patch( 'vim.tabpages', [ current_tab ] ):
with MockVimBuffers( [ current_buffer, different_buffer ],
current_buffer ) as vim:
[ current_buffer ] ) as vim:
vimsupport.JumpToLocation( os.path.realpath( u'different_uni¢𐍈d€' ),
2, 5 )

View File

@ -28,8 +28,8 @@ MockVimModule()
import os
import sys
from hamcrest import ( assert_that, contains, empty, equal_to, is_in, is_not,
matches_regexp )
from hamcrest import ( assert_that, contains, empty, equal_to, has_entries,
is_in, is_not, matches_regexp )
from mock import call, MagicMock, patch
from ycm.paths import _PathToPythonUsedDuringBuild
@ -195,7 +195,7 @@ def YouCompleteMe_DebugInfo_ServerRunning_test( ycm ):
_LoadExtraConfFile( extra_conf )
current_buffer = VimBuffer( buf_name, filetype = 'cpp' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
assert_that(
ycm.DebugInfo(),
matches_regexp(
@ -224,7 +224,7 @@ def YouCompleteMe_DebugInfo_ServerNotRunning_test( ycm ):
StopServer( ycm )
current_buffer = VimBuffer( 'current_buffer' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
assert_that(
ycm.DebugInfo(),
matches_regexp(
@ -264,8 +264,8 @@ def YouCompleteMe_OnVimLeave_KeepClientLogfile_test( ycm ):
def YouCompleteMe_ToggleLogs_WithParameters_test( ycm,
open_filename,
close_buffers_for_filename ):
logfile_buffer = VimBuffer( ycm._client_logfile, window = 1 )
with MockVimBuffers( [ logfile_buffer ], logfile_buffer ):
logfile_buffer = VimBuffer( ycm._client_logfile )
with MockVimBuffers( [ logfile_buffer ], [ logfile_buffer ] ):
ycm.ToggleLogs( os.path.basename( ycm._client_logfile ),
'nonexisting_logfile',
os.path.basename( ycm._server_stdout ) )
@ -290,7 +290,7 @@ def YouCompleteMe_ToggleLogs_WithoutParameters_SelectLogfileNotAlreadyOpen_test(
ycm, open_filename, *args ):
current_buffer = VimBuffer( 'current_buffer' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
ycm.ToggleLogs()
open_filename.assert_has_exact_calls( [
@ -309,8 +309,8 @@ def YouCompleteMe_ToggleLogs_WithoutParameters_SelectLogfileNotAlreadyOpen_test(
def YouCompleteMe_ToggleLogs_WithoutParameters_SelectLogfileAlreadyOpen_test(
ycm, close_buffers_for_filename, *args ):
logfile_buffer = VimBuffer( ycm._server_stdout, window = 1 )
with MockVimBuffers( [ logfile_buffer ], logfile_buffer ):
logfile_buffer = VimBuffer( ycm._server_stdout )
with MockVimBuffers( [ logfile_buffer ], [ logfile_buffer ] ):
ycm.ToggleLogs()
close_buffers_for_filename.assert_has_exact_calls( [
@ -326,7 +326,7 @@ def YouCompleteMe_ToggleLogs_WithoutParameters_NoSelection_test(
ycm, post_vim_message, *args ):
current_buffer = VimBuffer( 'current_buffer' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
ycm.ToggleLogs()
assert_that(
@ -339,7 +339,7 @@ def YouCompleteMe_ToggleLogs_WithoutParameters_NoSelection_test(
@YouCompleteMeInstance()
def YouCompleteMe_GetDefinedSubcommands_ListFromServer_test( ycm ):
current_buffer = VimBuffer( 'buffer' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with patch( 'ycm.client.base_request._JsonFromFuture',
return_value = [ 'SomeCommand', 'AnotherCommand' ] ):
assert_that(
@ -358,7 +358,7 @@ def YouCompleteMe_GetDefinedSubcommands_ErrorFromServer_test( ycm,
post_vim_message,
logger ):
current_buffer = VimBuffer( 'buffer' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with patch( 'ycm.client.base_request._JsonFromFuture',
side_effect = ServerError( 'Server error' ) ):
result = ycm.GetDefinedSubcommands()
@ -376,7 +376,7 @@ def YouCompleteMe_ShowDetailedDiagnostic_MessageFromServer_test(
ycm, post_vim_message ):
current_buffer = VimBuffer( 'buffer' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with patch( 'ycm.client.base_request._JsonFromFuture',
return_value = { 'message': 'some_detailed_diagnostic' } ):
ycm.ShowDetailedDiagnostic(),
@ -392,7 +392,7 @@ def YouCompleteMe_ShowDetailedDiagnostic_Exception_test(
ycm, post_vim_message ):
current_buffer = VimBuffer( 'buffer' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with patch( 'ycm.client.base_request._JsonFromFuture',
side_effect = RuntimeError( 'Some exception' ) ):
ycm.ShowDetailedDiagnostic(),
@ -408,7 +408,7 @@ def YouCompleteMe_ShowDiagnostics_FiletypeNotSupported_test( ycm,
post_vim_message ):
current_buffer = VimBuffer( 'buffer', filetype = 'not_supported' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
ycm.ShowDiagnostics()
post_vim_message.assert_called_once_with(
@ -424,8 +424,8 @@ def YouCompleteMe_ShowDiagnostics_FiletypeNotSupported_test( ycm,
def YouCompleteMe_ShowDiagnostics_NoDiagnosticsDetected_test(
ycm, set_location_list_for_window, post_vim_message, *args ):
current_buffer = VimBuffer( 'buffer', filetype = 'cpp', window = 99 )
with MockVimBuffers( [ current_buffer ], current_buffer ):
current_buffer = VimBuffer( 'buffer', filetype = 'cpp' )
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with patch( 'ycm.client.event_notification.EventNotification.Response',
return_value = {} ):
ycm.ShowDiagnostics()
@ -436,7 +436,7 @@ def YouCompleteMe_ShowDiagnostics_NoDiagnosticsDetected_test(
call( 'Diagnostics refreshed', warning = False ),
call( 'No warnings or errors detected.', warning = False )
] )
set_location_list_for_window.assert_called_once_with( 0, [] )
set_location_list_for_window.assert_called_once_with( 1, [] )
@YouCompleteMeInstance( { 'g:ycm_log_level': 'debug',
@ -461,9 +461,8 @@ def YouCompleteMe_ShowDiagnostics_DiagnosticsFound_DoNotOpenLocationList_test(
current_buffer = VimBuffer( 'buffer',
filetype = 'cpp',
number = 3,
window = 99 )
with MockVimBuffers( [ current_buffer ], current_buffer ):
number = 3 )
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with patch( 'ycm.client.event_notification.EventNotification.Response',
return_value = [ diagnostic ] ):
ycm.ShowDiagnostics()
@ -473,7 +472,7 @@ def YouCompleteMe_ShowDiagnostics_DiagnosticsFound_DoNotOpenLocationList_test(
warning = False ),
call( 'Diagnostics refreshed', warning = False )
] )
set_location_list_for_window.assert_called_once_with( 0, [ {
set_location_list_for_window.assert_called_once_with( 1, [ {
'bufnr': 3,
'lnum': 19,
'col': 2,
@ -508,9 +507,8 @@ def YouCompleteMe_ShowDiagnostics_DiagnosticsFound_OpenLocationList_test(
current_buffer = VimBuffer( 'buffer',
filetype = 'cpp',
number = 3,
window = 99 )
with MockVimBuffers( [ current_buffer ], current_buffer ):
number = 3 )
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
with patch( 'ycm.client.event_notification.EventNotification.Response',
return_value = [ diagnostic ] ):
ycm.ShowDiagnostics()
@ -520,7 +518,7 @@ def YouCompleteMe_ShowDiagnostics_DiagnosticsFound_OpenLocationList_test(
warning = False ),
call( 'Diagnostics refreshed', warning = False )
] )
set_location_list_for_window.assert_called_once_with( 0, [ {
set_location_list_for_window.assert_called_once_with( 1, [ {
'bufnr': 3,
'lnum': 19,
'col': 2,
@ -607,13 +605,12 @@ def YouCompleteMe_UpdateDiagnosticInterface_PrioritizeErrorsOverWarnings_test(
current_buffer = VimBuffer( 'buffer',
filetype = 'c',
contents = contents.splitlines(),
number = 5,
window = 2 )
number = 5 )
test_utils.VIM_MATCHES = []
test_utils.VIM_MATCHES_FOR_WINDOW.clear()
test_utils.VIM_SIGNS = []
with MockVimBuffers( [ current_buffer ], current_buffer, ( 3, 1 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 3, 1 ) ):
with patch( 'ycm.client.event_notification.EventNotification.Response',
return_value = diagnostics ):
ycm.OnFileReadyToParse()
@ -626,12 +623,14 @@ def YouCompleteMe_UpdateDiagnosticInterface_PrioritizeErrorsOverWarnings_test(
# Error match is added after warning matches.
assert_that(
test_utils.VIM_MATCHES,
contains(
test_utils.VIM_MATCHES_FOR_WINDOW,
has_entries( {
1: contains(
VimMatch( 'YcmWarningSection', '\%3l\%5c\_.\{-}\%3l\%7c' ),
VimMatch( 'YcmWarningSection', '\%3l\%3c\_.\{-}\%3l\%9c' ),
VimMatch( 'YcmErrorSection', '\%3l\%8c' )
)
} )
)
# Only the error sign is placed.
@ -643,19 +642,19 @@ def YouCompleteMe_UpdateDiagnosticInterface_PrioritizeErrorsOverWarnings_test(
)
# The error is not echoed again when moving the cursor along the line.
with MockVimBuffers( [ current_buffer ], current_buffer, ( 3, 2 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 3, 2 ) ):
post_vim_message.reset_mock()
ycm.OnCursorMoved()
post_vim_message.assert_not_called()
# The error is cleared when moving the cursor to another line.
with MockVimBuffers( [ current_buffer ], current_buffer, ( 2, 2 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 2, 2 ) ):
post_vim_message.reset_mock()
ycm.OnCursorMoved()
post_vim_message.assert_called_once_with( "", warning = False )
# The error is echoed when moving the cursor back.
with MockVimBuffers( [ current_buffer ], current_buffer, ( 3, 2 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 3, 2 ) ):
post_vim_message.reset_mock()
ycm.OnCursorMoved()
post_vim_message.assert_called_once_with(
@ -668,11 +667,13 @@ def YouCompleteMe_UpdateDiagnosticInterface_PrioritizeErrorsOverWarnings_test(
ycm.HandleFileParseRequest( block = True )
assert_that(
test_utils.VIM_MATCHES,
contains(
test_utils.VIM_MATCHES_FOR_WINDOW,
has_entries( {
1: contains(
VimMatch( 'YcmWarningSection', '\%3l\%5c\_.\{-}\%3l\%7c' ),
VimMatch( 'YcmWarningSection', '\%3l\%3c\_.\{-}\%3l\%9c' )
)
} )
)
assert_that(
@ -687,23 +688,25 @@ def YouCompleteMe_UpdateDiagnosticInterface_PrioritizeErrorsOverWarnings_test(
def YouCompleteMe_UpdateMatches_ClearDiagnosticMatchesInNewBuffer_test( ycm ):
current_buffer = VimBuffer( 'buffer',
filetype = 'c',
number = 5,
window = 2 )
number = 5 )
test_utils.VIM_MATCHES = [
test_utils.VIM_MATCHES_FOR_WINDOW.clear()
test_utils.VIM_MATCHES_FOR_WINDOW[ 1 ] = [
VimMatch( 'YcmWarningSection', '\%3l\%5c\_.\{-}\%3l\%7c' ),
VimMatch( 'YcmWarningSection', '\%3l\%3c\_.\{-}\%3l\%9c' ),
VimMatch( 'YcmErrorSection', '\%3l\%8c' )
]
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
ycm.UpdateMatches()
assert_that( test_utils.VIM_MATCHES, empty() )
assert_that( test_utils.VIM_MATCHES_FOR_WINDOW,
has_entries( { 1: empty() } ) )
@YouCompleteMeInstance( { 'g:ycm_echo_current_diagnostic': 1,
'g:ycm_always_populate_location_list': 1 } )
'g:ycm_always_populate_location_list': 1,
'g:ycm_enable_diagnostic_highlighting': 1 } )
@patch.object( ycm_buffer_module,
'DIAGNOSTIC_UI_ASYNC_FILETYPES',
[ 'ycmtest' ] )
@ -731,6 +734,19 @@ def YouCompleteMe_AsyncDiagnosticUpdate_SingleFile_test( ycm,
'line_num': 1,
'column_num': 1
},
'location_extent': {
'start': {
'filepath': '/current',
'line_num': 1,
'column_num': 1,
},
'end': {
'filepath': '/current',
'line_num': 1,
'column_num': 1,
}
},
'ranges': []
},
{
'kind': 'ERROR',
@ -740,6 +756,19 @@ def YouCompleteMe_AsyncDiagnosticUpdate_SingleFile_test( ycm,
'line_num': 4,
'column_num': 2
},
'location_extent': {
'start': {
'filepath': '/has_diags',
'line_num': 4,
'column_num': 2,
},
'end': {
'filepath': '/has_diags',
'line_num': 4,
'column_num': 2,
}
},
'ranges': []
},
{
'kind': 'ERROR',
@ -749,33 +778,46 @@ def YouCompleteMe_AsyncDiagnosticUpdate_SingleFile_test( ycm,
'line_num': 8,
'column_num': 4
},
'location_extent': {
'start': {
'filepath': '/not_open',
'line_num': 8,
'column_num': 4,
},
'end': {
'filepath': '/not_open',
'line_num': 8,
'column_num': 4,
}
},
'ranges': []
}
]
current_buffer = VimBuffer( '/current',
filetype = 'ycmtest',
number = 1,
window = 10 )
buffers = [
current_buffer,
VimBuffer( '/no_diags',
contents = [ 'current' ] * 10,
number = 1 )
no_diags_buffer = VimBuffer( '/no_diags',
filetype = 'ycmtest',
number = 2,
window = 9 ),
VimBuffer( '/has_diags',
contents = [ 'nodiags' ] * 10,
number = 2 )
hidden_buffer = VimBuffer( '/has_diags',
filetype = 'ycmtest',
number = 3,
window = 8 ),
]
contents = [ 'hasdiags' ] * 10,
number = 3 )
buffers = [ current_buffer, no_diags_buffer, hidden_buffer ]
windows = [ current_buffer, no_diags_buffer ]
# Register each buffer internally with YCM
for current in buffers:
with MockVimBuffers( buffers, current, ( 1, 1 ) ):
with MockVimBuffers( buffers, [ current ] ):
ycm.OnFileReadyToParse()
with patch( 'ycm.vimsupport.SetLocationListForWindow',
new_callable = ExtendedMock ) as set_location_list_for_window:
with MockVimBuffers( buffers, current_buffer, ( 1, 1 ) ):
with MockVimBuffers( buffers, windows ):
ycm.UpdateWithNewDiagnosticsForFile( '/current', diagnostics )
# We update the diagnostic on the current cursor position
@ -785,7 +827,7 @@ def YouCompleteMe_AsyncDiagnosticUpdate_SingleFile_test( ycm,
# Ensure we included all the diags though
set_location_list_for_window.assert_has_exact_calls( [
call( 0, [
call( 1, [
{
'lnum': 1,
'col': 1,
@ -816,9 +858,19 @@ def YouCompleteMe_AsyncDiagnosticUpdate_SingleFile_test( ycm,
] )
] )
assert_that(
test_utils.VIM_MATCHES_FOR_WINDOW,
has_entries( {
1: contains(
VimMatch( 'YcmErrorSection', '\%1l\%1c\_.\{-}\%1l\%1c' )
)
} )
)
@YouCompleteMeInstance( { 'g:ycm_echo_current_diagnostic': 1,
'g:ycm_always_populate_location_list': 1 } )
'g:ycm_always_populate_location_list': 1,
'g:ycm_enable_diagnostic_highlighting': 1 } )
@patch.object( ycm_buffer_module,
'DIAGNOSTIC_UI_ASYNC_FILETYPES',
[ 'ycmtest' ] )
@ -841,15 +893,65 @@ def YouCompleteMe_AsyncDiagnosticUpdate_PerFile_test( ycm,
'filepath': '/current',
'line_num': 1,
'column_num': 1
}, }, ] ),
( '/has_diags', [ {
},
'location_extent': {
'start': {
'filepath': '/current',
'line_num': 1,
'column_num': 1,
},
'end': {
'filepath': '/current',
'line_num': 1,
'column_num': 1,
}
},
'ranges': [],
} ] ),
( '/separate_window', [ {
'kind': 'ERROR',
'text': 'error text in a buffer open in a separate window',
'location': {
'filepath': '/separate_window',
'line_num': 3,
'column_num': 3
},
'location_extent': {
'start': {
'filepath': '/separate_window',
'line_num': 3,
'column_num': 3,
},
'end': {
'filepath': '/separate_window',
'line_num': 3,
'column_num': 3,
}
},
'ranges': []
} ] ),
( '/hidden', [ {
'kind': 'ERROR',
'text': 'error text in hidden buffer',
'location': {
'filepath': '/has_diags',
'filepath': '/hidden',
'line_num': 4,
'column_num': 2
}, }, ] ),
},
'location_extent': {
'start': {
'filepath': '/hidden',
'line_num': 4,
'column_num': 2,
},
'end': {
'filepath': '/hidden',
'line_num': 4,
'column_num': 2,
}
},
'ranges': []
} ] ),
( '/not_open', [ {
'kind': 'ERROR',
'text': 'error text in buffer not open in Vim',
@ -857,33 +959,59 @@ def YouCompleteMe_AsyncDiagnosticUpdate_PerFile_test( ycm,
'filepath': '/not_open',
'line_num': 8,
'column_num': 4
}, }, ] )
},
'location_extent': {
'start': {
'filepath': '/not_open',
'line_num': 8,
'column_num': 4,
},
'end': {
'filepath': '/not_open',
'line_num': 8,
'column_num': 4,
}
},
'ranges': []
} ] )
]
current_buffer = VimBuffer( '/current',
filetype = 'ycmtest',
number = 1,
window = 10 )
contents = [ 'current' ] * 10,
number = 1 )
no_diags_buffer = VimBuffer( '/no_diags',
filetype = 'ycmtest',
contents = [ 'no_diags' ] * 10,
number = 2 )
separate_window = VimBuffer( '/separate_window',
filetype = 'ycmtest',
contents = [ 'separate_window' ] * 10,
number = 3 )
hidden_buffer = VimBuffer( '/hidden',
filetype = 'ycmtest',
contents = [ 'hidden' ] * 10,
number = 4 )
buffers = [
current_buffer,
VimBuffer( '/no_diags',
filetype = 'ycmtest',
number = 2,
window = 9 ),
VimBuffer( '/has_diags',
filetype = 'ycmtest',
number = 3,
window = 8 ),
no_diags_buffer,
separate_window,
hidden_buffer
]
windows = [
current_buffer,
no_diags_buffer,
separate_window
]
# Register each buffer internally with YCM
for current in buffers:
with MockVimBuffers( buffers, current, ( 1, 1 ) ):
with MockVimBuffers( buffers, [ current ] ):
ycm.OnFileReadyToParse()
with patch( 'ycm.vimsupport.SetLocationListForWindow',
new_callable = ExtendedMock ) as set_location_list_for_window:
with MockVimBuffers( buffers, current_buffer, ( 1, 1 ) ):
with MockVimBuffers( buffers, windows ):
for filename, diagnostics in diagnostics_per_file:
ycm.UpdateWithNewDiagnosticsForFile( filename, diagnostics )
@ -894,7 +1022,7 @@ def YouCompleteMe_AsyncDiagnosticUpdate_PerFile_test( ycm,
# Ensure we included all the diags though
set_location_list_for_window.assert_has_exact_calls( [
call( 0, [
call( 1, [
{
'lnum': 1,
'col': 1,
@ -905,18 +1033,30 @@ def YouCompleteMe_AsyncDiagnosticUpdate_PerFile_test( ycm,
},
] ),
call( 8, [
call( 3, [
{
'lnum': 4,
'col': 2,
'lnum': 3,
'col': 3,
'bufnr': 3,
'valid': 1,
'type': 'E',
'text': 'error text in hidden buffer',
'text': 'error text in a buffer open in a separate window',
},
] )
] )
assert_that(
test_utils.VIM_MATCHES_FOR_WINDOW,
has_entries( {
1: contains(
VimMatch( 'YcmErrorSection', '\%1l\%1c\_.\{-}\%1l\%1c' )
),
3: contains(
VimMatch( 'YcmErrorSection', '\%3l\%3c\_.\{-}\%3l\%3c' )
)
} )
)
@YouCompleteMeInstance()
def YouCompleteMe_OnPeriodicTick_ServerNotRunning_test( ycm, *args ):
@ -945,12 +1085,10 @@ def YouCompleteMe_OnPeriodicTick_DontRetry_test( ycm,
current_buffer = VimBuffer( '/current',
filetype = 'ycmtest',
number = 1,
window = 10 )
buffers = [ current_buffer ]
number = 1 )
# Create the request and make the first poll; we expect no response
with MockVimBuffers( buffers, current_buffer, ( 1, 1 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 1 ) ):
assert_that( ycm.OnPeriodicTick(), equal_to( True ) )
post_data_to_handler_async.assert_called()
@ -996,12 +1134,10 @@ def YouCompleteMe_OnPeriodicTick_Exception_test( ycm,
current_buffer = VimBuffer( '/current',
filetype = 'ycmtest',
number = 1,
window = 10 )
buffers = [ current_buffer ]
number = 1 )
# Create the request and make the first poll; we expect no response
with MockVimBuffers( buffers, current_buffer, ( 1, 1 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 1 ) ):
assert_that( ycm.OnPeriodicTick(), equal_to( True ) )
post_data_to_handler_async.assert_called()
@ -1036,12 +1172,10 @@ def YouCompleteMe_OnPeriodicTick_ValidResponse_test( ycm,
current_buffer = VimBuffer( '/current',
filetype = 'ycmtest',
number = 1,
window = 10 )
buffers = [ current_buffer ]
number = 1 )
# Create the request and make the first poll; we expect no response
with MockVimBuffers( buffers, current_buffer, ( 1, 1 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 1 ) ):
assert_that( ycm.OnPeriodicTick(), equal_to( True ) )
post_data_to_handler_async.assert_called()
@ -1065,7 +1199,7 @@ def YouCompleteMe_OnPeriodicTick_ValidResponse_test( ycm,
def YouCompleteMe_OnCompleteDone_CompletionRequest_test( ycm,
on_complete_done ):
current_buffer = VimBuffer( 'current_buffer' )
with MockVimBuffers( [ current_buffer ], current_buffer, ( 1, 1 ) ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ], ( 1, 1 ) ):
ycm.SendCompletionRequest()
ycm.OnCompleteDone()
on_complete_done.assert_called()
@ -1082,5 +1216,5 @@ def YouCompleteMe_OnCompleteDone_NoCompletionRequest_test( ycm,
@YouCompleteMeInstance()
def YouCompleteMe_ShouldResendFileParseRequest_NoParseRequest_test( ycm ):
current_buffer = VimBuffer( 'current_buffer' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with MockVimBuffers( [ current_buffer ], [ current_buffer ] ):
assert_that( ycm.ShouldResendFileParseRequest(), equal_to( False ) )

View File

@ -23,6 +23,7 @@ from __future__ import absolute_import
from builtins import * # noqa
from future.utils import iterkeys
import contextlib
import vim
import os
import json
@ -289,36 +290,18 @@ def SetLocationList( diagnostics ):
SetLocationListForWindow( 0, diagnostics )
def GetWindowNumberForBufferDiagnostics( buffer_number ):
"""Return an appropriate window number to use for displaying diagnostics
associated with the buffer number supplied. Always returns a valid window
number or 0 meaning the current window."""
# Location lists are associated with _windows_ not _buffers_. This makes a lot
# of sense, but YCM associates diagnostics with _buffers_, because it is the
# buffer that actually gets parsed.
#
# The heuristic we use is to determine any open window for a specified buffer,
# and set that. If there is no such window on the current tab page, we use the
# current window (by passing 0 as the window number)
if buffer_number == vim.current.buffer.number:
return 0
window_number = GetIntValue( "bufwinnr({0})".format( buffer_number ) )
if window_number < 0:
return 0
return window_number
def GetWindowsForBufferNumber( buffer_number ):
"""Return the list of windows containing the buffer with number
|buffer_number| for the current tab page."""
return [ window for window in vim.windows
if window.buffer.number == buffer_number ]
def SetLocationListForBuffer( buffer_number, diagnostics ):
"""Populate the location list of an apppropriate window for the supplied
buffer number. See SetLocationListForWindow for format of diagnostics."""
return SetLocationListForWindow(
GetWindowNumberForBufferDiagnostics( buffer_number ),
diagnostics )
def SetLocationListsForBuffer( buffer_number, diagnostics ):
"""Populate location lists for all windows containing the buffer with number
|buffer_number|. See SetLocationListForWindow for format of diagnostics."""
for window in GetWindowsForBufferNumber( buffer_number ):
SetLocationListForWindow( window.number, diagnostics )
def SetLocationListForWindow( window_number, diagnostics ):
@ -1181,3 +1164,39 @@ def BuildRange( start_line, end_line ):
}
}
}
@contextlib.contextmanager
def AutocommandEventsIgnored( events = [ 'all' ] ):
"""Context manager to perform operations without triggering autocommand
events. |events| is a list of events to ignore. By default, all events are
ignored."""
old_eventignore = vim.options[ 'eventignore' ]
ignored_events = {
event for event in ToUnicode( old_eventignore ).split( ',' ) if event }
ignored_events.update( events )
vim.options[ 'eventignore' ] = ','.join( ignored_events )
try:
yield
finally:
vim.options[ 'eventignore' ] = old_eventignore
@contextlib.contextmanager
def CurrentWindow():
"""Context manager to perform operations on other windows than the current one
without triggering autocommands related to window movement. Use the
SwitchWindow function to move to other windows while under the context."""
current_window = vim.current.window
with AutocommandEventsIgnored( [ 'WinEnter', 'Winleave' ] ):
try:
yield
finally:
vim.current.window = current_window
def SwitchWindow( window ):
"""Move to the window object |window|. This function should be called under
the CurrentWindow context if you are going to switch back to the original
window."""
vim.current.window = window

View File

@ -385,7 +385,7 @@ class YouCompleteMe( object ):
bufnr = vimsupport.GetBufferNumberForFilename( filepath )
if bufnr in self._buffers and vimsupport.BufferIsVisible( bufnr ):
# Note: We only update location lists, etc. for visible buffers, because
# otherwise we defualt to using the curren location list and the results
# otherwise we default to using the current location list and the results
# are that non-visible buffer errors clobber visible ones.
self._buffers[ bufnr ].UpdateWithNewDiagnostics( diagnostics )
else: