Refactored diag interface, removed dummy sign.
This commit is contained in:
parent
b20809332c
commit
22be4e777d
@ -38,7 +38,7 @@ class Buffer( object ):
|
|||||||
self._parse_tick = 0
|
self._parse_tick = 0
|
||||||
self._handled_tick = 0
|
self._handled_tick = 0
|
||||||
self._parse_request = None
|
self._parse_request = None
|
||||||
self._diag_interface = DiagnosticInterface( user_options )
|
self._diag_interface = DiagnosticInterface( bufnr, user_options )
|
||||||
|
|
||||||
|
|
||||||
def FileParseRequestReady( self, block = False ):
|
def FileParseRequestReady( self, block = False ):
|
||||||
|
@ -30,17 +30,17 @@ import vim
|
|||||||
|
|
||||||
|
|
||||||
class DiagnosticInterface( object ):
|
class DiagnosticInterface( object ):
|
||||||
def __init__( self, user_options ):
|
def __init__( self, bufnr, user_options ):
|
||||||
|
self._bufnr = bufnr
|
||||||
self._user_options = user_options
|
self._user_options = user_options
|
||||||
self._diagnostics = []
|
self._diagnostics = []
|
||||||
self._diag_filter = DiagnosticFilter.CreateFromOptions( user_options )
|
self._diag_filter = DiagnosticFilter.CreateFromOptions( user_options )
|
||||||
# Line and column numbers are 1-based
|
# Line and column numbers are 1-based
|
||||||
self._buffer_number_to_line_to_diags = defaultdict(
|
self._line_to_diags = defaultdict( list )
|
||||||
lambda: defaultdict( list ) )
|
self._placed_signs = []
|
||||||
self._next_sign_id = 1
|
self._next_sign_id = 1
|
||||||
self._previous_line_number = -1
|
self._previous_line_number = -1
|
||||||
self._diag_message_needs_clearing = False
|
self._diag_message_needs_clearing = False
|
||||||
self._placed_signs = []
|
|
||||||
|
|
||||||
|
|
||||||
def OnCursorMoved( self ):
|
def OnCursorMoved( self ):
|
||||||
@ -54,11 +54,11 @@ class DiagnosticInterface( object ):
|
|||||||
|
|
||||||
|
|
||||||
def GetErrorCount( self ):
|
def GetErrorCount( self ):
|
||||||
return len( self._FilterDiagnostics( _DiagnosticIsError ) )
|
return self._DiagnosticsCount( _DiagnosticIsError )
|
||||||
|
|
||||||
|
|
||||||
def GetWarningCount( self ):
|
def GetWarningCount( self ):
|
||||||
return len( self._FilterDiagnostics( _DiagnosticIsWarning ) )
|
return self._DiagnosticsCount( _DiagnosticIsWarning )
|
||||||
|
|
||||||
|
|
||||||
def PopulateLocationList( self ):
|
def PopulateLocationList( self ):
|
||||||
@ -71,38 +71,26 @@ class DiagnosticInterface( object ):
|
|||||||
def UpdateWithNewDiagnostics( self, diags ):
|
def UpdateWithNewDiagnostics( self, diags ):
|
||||||
self._diagnostics = [ _NormalizeDiagnostic( x ) for x in
|
self._diagnostics = [ _NormalizeDiagnostic( x ) for x in
|
||||||
self._ApplyDiagnosticFilter( diags ) ]
|
self._ApplyDiagnosticFilter( diags ) ]
|
||||||
self._buffer_number_to_line_to_diags = _ConvertDiagListToDict(
|
self._ConvertDiagListToDict()
|
||||||
self._diagnostics )
|
|
||||||
|
|
||||||
if self._user_options[ 'enable_diagnostic_signs' ]:
|
if self._user_options[ 'enable_diagnostic_signs' ]:
|
||||||
self._placed_signs, self._next_sign_id = _UpdateSigns(
|
self._UpdateSigns()
|
||||||
self._placed_signs,
|
|
||||||
self._buffer_number_to_line_to_diags,
|
|
||||||
self._next_sign_id )
|
|
||||||
|
|
||||||
if self._user_options[ 'enable_diagnostic_highlighting' ]:
|
if self._user_options[ 'enable_diagnostic_highlighting' ]:
|
||||||
_UpdateSquiggles( self._buffer_number_to_line_to_diags )
|
self._UpdateSquiggles()
|
||||||
|
|
||||||
if self._user_options[ 'always_populate_location_list' ]:
|
if self._user_options[ 'always_populate_location_list' ]:
|
||||||
self._UpdateLocationList()
|
self._UpdateLocationList()
|
||||||
|
|
||||||
|
|
||||||
def _ApplyDiagnosticFilter( self, diags, extra_predicate = None ):
|
def _ApplyDiagnosticFilter( self, diags ):
|
||||||
filetypes = vimsupport.CurrentFiletypes()
|
filetypes = vimsupport.GetBufferFiletypes( self._bufnr )
|
||||||
diag_filter = self._diag_filter.SubsetForTypes( filetypes )
|
diag_filter = self._diag_filter.SubsetForTypes( filetypes )
|
||||||
predicate = diag_filter.IsAllowed
|
return filter( diag_filter.IsAllowed, diags )
|
||||||
if extra_predicate is not None:
|
|
||||||
def Filter( diag ):
|
|
||||||
return extra_predicate( diag ) and diag_filter.IsAllowed( diag )
|
|
||||||
|
|
||||||
predicate = Filter
|
|
||||||
|
|
||||||
return filter( predicate, diags )
|
|
||||||
|
|
||||||
|
|
||||||
def _EchoDiagnosticForLine( self, line_num ):
|
def _EchoDiagnosticForLine( self, line_num ):
|
||||||
buffer_num = vim.current.buffer.number
|
diags = self._line_to_diags[ line_num ]
|
||||||
diags = self._buffer_number_to_line_to_diags[ buffer_num ][ line_num ]
|
|
||||||
if not diags:
|
if not diags:
|
||||||
if self._diag_message_needs_clearing:
|
if self._diag_message_needs_clearing:
|
||||||
# Clear any previous diag echo
|
# Clear any previous diag echo
|
||||||
@ -119,15 +107,11 @@ class DiagnosticInterface( object ):
|
|||||||
self._diag_message_needs_clearing = True
|
self._diag_message_needs_clearing = True
|
||||||
|
|
||||||
|
|
||||||
def _FilterDiagnostics( self, predicate ):
|
def _DiagnosticsCount( self, predicate ):
|
||||||
matched_diags = []
|
count = 0
|
||||||
line_to_diags = self._buffer_number_to_line_to_diags[
|
for diags in itervalues( self._line_to_diags ):
|
||||||
vim.current.buffer.number ]
|
count += sum( 1 for d in diags if predicate( d ) )
|
||||||
|
return count
|
||||||
for diags in itervalues( line_to_diags ):
|
|
||||||
matched_diags.extend( list(
|
|
||||||
self._ApplyDiagnosticFilter( diags, predicate ) ) )
|
|
||||||
return matched_diags
|
|
||||||
|
|
||||||
|
|
||||||
def _UpdateLocationList( self ):
|
def _UpdateLocationList( self ):
|
||||||
@ -135,133 +119,92 @@ class DiagnosticInterface( object ):
|
|||||||
vimsupport.ConvertDiagnosticsToQfList( self._diagnostics ) )
|
vimsupport.ConvertDiagnosticsToQfList( self._diagnostics ) )
|
||||||
|
|
||||||
|
|
||||||
def _UpdateSquiggles( buffer_number_to_line_to_diags ):
|
def _UpdateSquiggles( self ):
|
||||||
vimsupport.ClearYcmSyntaxMatches()
|
if self._bufnr != vim.current.buffer.number:
|
||||||
line_to_diags = buffer_number_to_line_to_diags[ vim.current.buffer.number ]
|
return
|
||||||
|
|
||||||
for diags in itervalues( line_to_diags ):
|
vimsupport.ClearYcmSyntaxMatches()
|
||||||
# Insert squiggles in reverse order so that errors overlap warnings.
|
|
||||||
for diag in reversed( diags ):
|
|
||||||
location_extent = diag[ 'location_extent' ]
|
|
||||||
is_error = _DiagnosticIsError( diag )
|
|
||||||
|
|
||||||
if location_extent[ 'start' ][ 'line_num' ] <= 0:
|
for diags in itervalues( self._line_to_diags ):
|
||||||
location = diag[ 'location' ]
|
for diag in diags:
|
||||||
vimsupport.AddDiagnosticSyntaxMatch(
|
location_extent = diag[ 'location_extent' ]
|
||||||
location[ 'line_num' ],
|
is_error = _DiagnosticIsError( diag )
|
||||||
location[ 'column_num' ],
|
|
||||||
is_error = is_error )
|
|
||||||
else:
|
|
||||||
vimsupport.AddDiagnosticSyntaxMatch(
|
|
||||||
location_extent[ 'start' ][ 'line_num' ],
|
|
||||||
location_extent[ 'start' ][ 'column_num' ],
|
|
||||||
location_extent[ 'end' ][ 'line_num' ],
|
|
||||||
location_extent[ 'end' ][ 'column_num' ],
|
|
||||||
is_error = is_error )
|
|
||||||
|
|
||||||
for diag_range in diag[ 'ranges' ]:
|
if location_extent[ 'start' ][ 'line_num' ] <= 0:
|
||||||
vimsupport.AddDiagnosticSyntaxMatch(
|
location = diag[ 'location' ]
|
||||||
diag_range[ 'start' ][ 'line_num' ],
|
vimsupport.AddDiagnosticSyntaxMatch(
|
||||||
diag_range[ 'start' ][ 'column_num' ],
|
location[ 'line_num' ],
|
||||||
diag_range[ 'end' ][ 'line_num' ],
|
location[ 'column_num' ],
|
||||||
diag_range[ 'end' ][ 'column_num' ],
|
is_error = is_error )
|
||||||
is_error = is_error )
|
else:
|
||||||
|
vimsupport.AddDiagnosticSyntaxMatch(
|
||||||
|
location_extent[ 'start' ][ 'line_num' ],
|
||||||
|
location_extent[ 'start' ][ 'column_num' ],
|
||||||
|
location_extent[ 'end' ][ 'line_num' ],
|
||||||
|
location_extent[ 'end' ][ 'column_num' ],
|
||||||
|
is_error = is_error )
|
||||||
|
|
||||||
|
for diag_range in diag[ 'ranges' ]:
|
||||||
|
vimsupport.AddDiagnosticSyntaxMatch(
|
||||||
|
diag_range[ 'start' ][ 'line_num' ],
|
||||||
|
diag_range[ 'start' ][ 'column_num' ],
|
||||||
|
diag_range[ 'end' ][ 'line_num' ],
|
||||||
|
diag_range[ 'end' ][ 'column_num' ],
|
||||||
|
is_error = is_error )
|
||||||
|
|
||||||
|
|
||||||
def _UpdateSigns( placed_signs, buffer_number_to_line_to_diags, next_sign_id ):
|
def _UpdateSigns( self ):
|
||||||
new_signs, kept_signs, next_sign_id = _GetKeptAndNewSigns(
|
new_signs, obsolete_signs = self._GetNewAndObsoleteSigns()
|
||||||
placed_signs, buffer_number_to_line_to_diags, next_sign_id
|
|
||||||
)
|
|
||||||
# Dummy sign used to prevent "flickering" in Vim when last mark gets
|
|
||||||
# deleted from buffer. Dummy sign prevents Vim to collapsing the sign column
|
|
||||||
# in that case.
|
|
||||||
# There's also a vim bug which causes the whole window to redraw in some
|
|
||||||
# conditions (vim redraw logic is very complex). But, somehow, if we place a
|
|
||||||
# dummy sign before placing other "real" signs, it will not redraw the
|
|
||||||
# buffer (patch to vim pending).
|
|
||||||
dummy_sign_needed = not kept_signs and new_signs
|
|
||||||
|
|
||||||
if dummy_sign_needed:
|
self._PlaceNewSigns( new_signs )
|
||||||
vimsupport.PlaceDummySign( next_sign_id + 1,
|
|
||||||
vim.current.buffer.number,
|
|
||||||
new_signs[ 0 ].line )
|
|
||||||
|
|
||||||
# We place only those signs that haven't been placed yet.
|
self._UnplaceObsoleteSigns( obsolete_signs )
|
||||||
new_placed_signs = _PlaceNewSigns( kept_signs, new_signs )
|
|
||||||
|
|
||||||
# We use incremental placement, so signs that already placed on the correct
|
|
||||||
# lines will not be deleted and placed again, which should improve performance
|
|
||||||
# in case of many diags. Signs which don't exist in the current diag should be
|
|
||||||
# deleted.
|
|
||||||
_UnplaceObsoleteSigns( kept_signs, placed_signs )
|
|
||||||
|
|
||||||
if dummy_sign_needed:
|
|
||||||
vimsupport.UnPlaceDummySign( next_sign_id + 1, vim.current.buffer.number )
|
|
||||||
|
|
||||||
return new_placed_signs, next_sign_id
|
|
||||||
|
|
||||||
|
|
||||||
def _GetKeptAndNewSigns( placed_signs, buffer_number_to_line_to_diags,
|
def _GetNewAndObsoleteSigns( self ):
|
||||||
next_sign_id ):
|
new_signs = []
|
||||||
new_signs = []
|
obsolete_signs = list( self._placed_signs )
|
||||||
kept_signs = []
|
for line, diags in iteritems( self._line_to_diags ):
|
||||||
for buffer_number, line_to_diags in iteritems(
|
# We always go for the first diagnostic on line,
|
||||||
buffer_number_to_line_to_diags ):
|
# because it is sorted giving priority to the Errors.
|
||||||
if not vimsupport.BufferIsVisible( buffer_number ):
|
diag = diags[ 0 ]
|
||||||
continue
|
sign = _DiagSignPlacement( self._next_sign_id,
|
||||||
|
line, _DiagnosticIsError( diag ) )
|
||||||
for line, diags in iteritems( line_to_diags ):
|
try:
|
||||||
# Only one sign is visible by line.
|
obsolete_signs.remove( sign )
|
||||||
first_diag = diags[ 0 ]
|
except ValueError:
|
||||||
sign = _DiagSignPlacement( next_sign_id,
|
|
||||||
line,
|
|
||||||
buffer_number,
|
|
||||||
_DiagnosticIsError( first_diag ) )
|
|
||||||
if sign not in placed_signs:
|
|
||||||
new_signs.append( sign )
|
new_signs.append( sign )
|
||||||
next_sign_id += 1
|
self._next_sign_id += 1
|
||||||
else:
|
return new_signs, obsolete_signs
|
||||||
# We use .index here because `sign` contains a new id, but
|
|
||||||
# we need the sign with the old id to unplace it later on.
|
|
||||||
# We won't be placing the new sign.
|
|
||||||
kept_signs.append( placed_signs[ placed_signs.index( sign ) ] )
|
|
||||||
return new_signs, kept_signs, next_sign_id
|
|
||||||
|
|
||||||
|
|
||||||
def _PlaceNewSigns( kept_signs, new_signs ):
|
def _PlaceNewSigns( self, new_signs ):
|
||||||
placed_signs = kept_signs[:]
|
for sign in new_signs:
|
||||||
for sign in new_signs:
|
vimsupport.PlaceSign( sign.id, sign.line, self._bufnr, sign.is_error )
|
||||||
# Do not set two signs on the same line, it will screw up storing sign
|
self._placed_signs.append( sign )
|
||||||
# locations.
|
|
||||||
if sign in placed_signs:
|
|
||||||
continue
|
|
||||||
vimsupport.PlaceSign( sign.id, sign.line, sign.buffer, sign.is_error )
|
|
||||||
placed_signs.append( sign )
|
|
||||||
return placed_signs
|
|
||||||
|
|
||||||
|
|
||||||
def _UnplaceObsoleteSigns( kept_signs, placed_signs ):
|
def _UnplaceObsoleteSigns( self, obsolete_signs ):
|
||||||
for sign in placed_signs:
|
for sign in obsolete_signs:
|
||||||
if sign not in kept_signs:
|
self._placed_signs.remove( sign )
|
||||||
vimsupport.UnplaceSignInBuffer( sign.buffer, sign.id )
|
vimsupport.UnplaceSignInBuffer( self._bufnr, sign.id )
|
||||||
|
|
||||||
|
|
||||||
def _ConvertDiagListToDict( diag_list ):
|
def _ConvertDiagListToDict( self ):
|
||||||
buffer_to_line_to_diags = defaultdict( lambda: defaultdict( list ) )
|
self._line_to_diags = defaultdict( list )
|
||||||
for diag in diag_list:
|
for diag in self._diagnostics:
|
||||||
location = diag[ 'location' ]
|
location = diag[ 'location' ]
|
||||||
buffer_number = vimsupport.GetBufferNumberForFilename(
|
bufnr = vimsupport.GetBufferNumberForFilename( location[ 'filepath' ] )
|
||||||
location[ 'filepath' ] )
|
if bufnr != self._bufnr:
|
||||||
line_number = location[ 'line_num' ]
|
continue
|
||||||
buffer_to_line_to_diags[ buffer_number ][ line_number ].append( diag )
|
line_number = location[ 'line_num' ]
|
||||||
|
self._line_to_diags[ line_number ].append( diag )
|
||||||
|
|
||||||
for line_to_diags in itervalues( buffer_to_line_to_diags ):
|
for diags in itervalues( self._line_to_diags ):
|
||||||
for diags in itervalues( line_to_diags ):
|
# We also want errors to be listed before warnings so that errors aren't
|
||||||
# We want errors to be listed before warnings so that errors aren't hidden
|
# hidden by the warnings; Vim won't place a sign oven an existing one.
|
||||||
# by the warnings.
|
|
||||||
diags.sort( key = lambda diag: ( diag[ 'kind' ],
|
diags.sort( key = lambda diag: ( diag[ 'kind' ],
|
||||||
diag[ 'location' ][ 'column_num' ] ) )
|
diag[ 'location' ][ 'column_num' ] ) )
|
||||||
return buffer_to_line_to_diags
|
|
||||||
|
|
||||||
|
|
||||||
_DiagnosticIsError = CompileLevel( 'error' )
|
_DiagnosticIsError = CompileLevel( 'error' )
|
||||||
@ -278,12 +221,10 @@ def _NormalizeDiagnostic( diag ):
|
|||||||
return diag
|
return diag
|
||||||
|
|
||||||
|
|
||||||
class _DiagSignPlacement(
|
class _DiagSignPlacement( namedtuple( "_DiagSignPlacement",
|
||||||
namedtuple( "_DiagSignPlacement",
|
[ 'id', 'line', 'is_error' ] ) ):
|
||||||
[ 'id', 'line', 'buffer', 'is_error' ] ) ):
|
|
||||||
# We want two signs that have different ids but the same location to compare
|
# We want two signs that have different ids but the same location to compare
|
||||||
# equal. ID doesn't matter.
|
# equal. ID doesn't matter.
|
||||||
def __eq__( self, other ):
|
def __eq__( self, other ):
|
||||||
return ( self.line == other.line and
|
return ( self.line == other.line and
|
||||||
self.buffer == other.buffer and
|
|
||||||
self.is_error == other.is_error )
|
self.is_error == other.is_error )
|
||||||
|
@ -43,7 +43,7 @@ GETBUFVAR_REGEX = re.compile(
|
|||||||
'^getbufvar\((?P<buffer_number>[0-9]+), "(?P<option>.+)"\)$' )
|
'^getbufvar\((?P<buffer_number>[0-9]+), "(?P<option>.+)"\)$' )
|
||||||
MATCHADD_REGEX = re.compile(
|
MATCHADD_REGEX = re.compile(
|
||||||
'^matchadd\(\'(?P<group>.+)\', \'(?P<pattern>.+)\'\)$' )
|
'^matchadd\(\'(?P<group>.+)\', \'(?P<pattern>.+)\'\)$' )
|
||||||
MATCHDELETE_REGEX = re.compile( '^matchdelete\((?P<id>)\)$' )
|
MATCHDELETE_REGEX = re.compile( '^matchdelete\((?P<id>\d+)\)$' )
|
||||||
|
|
||||||
# One-and only instance of mocked Vim object. The first 'import vim' that is
|
# One-and only instance of mocked Vim object. The first 'import vim' that is
|
||||||
# executed binds the vim module to the instance of MagicMock that is created,
|
# executed binds the vim module to the instance of MagicMock that is created,
|
||||||
@ -139,7 +139,7 @@ def _MockVimOptionsEval( value ):
|
|||||||
|
|
||||||
def _MockVimMatchEval( value ):
|
def _MockVimMatchEval( value ):
|
||||||
if value == 'getmatches()':
|
if value == 'getmatches()':
|
||||||
return VIM_MATCHES
|
return list( VIM_MATCHES )
|
||||||
|
|
||||||
match = MATCHADD_REGEX.search( value )
|
match = MATCHADD_REGEX.search( value )
|
||||||
if match:
|
if match:
|
||||||
@ -151,7 +151,7 @@ def _MockVimMatchEval( value ):
|
|||||||
|
|
||||||
match = MATCHDELETE_REGEX.search( value )
|
match = MATCHDELETE_REGEX.search( value )
|
||||||
if match:
|
if match:
|
||||||
identity = match.group( 'id' )
|
identity = int( match.group( 'id' ) )
|
||||||
for index, vim_match in enumerate( VIM_MATCHES ):
|
for index, vim_match in enumerate( VIM_MATCHES ):
|
||||||
if vim_match.id == identity:
|
if vim_match.id == identity:
|
||||||
VIM_MATCHES.pop( index )
|
VIM_MATCHES.pop( index )
|
||||||
@ -270,6 +270,13 @@ class VimMatch( object ):
|
|||||||
self.pattern )
|
self.pattern )
|
||||||
|
|
||||||
|
|
||||||
|
def __getitem__( self, key ):
|
||||||
|
if key == 'group':
|
||||||
|
return self.group
|
||||||
|
elif key == 'id':
|
||||||
|
return self.id
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def MockVimBuffers( buffers, current_buffer, cursor_position = ( 1, 1 ),
|
def MockVimBuffers( buffers, current_buffer, cursor_position = ( 1, 1 ),
|
||||||
ycm_state = None):
|
ycm_state = None):
|
||||||
|
@ -524,19 +524,15 @@ def YouCompleteMe_UpdateDiagnosticInterface_PrioritizeErrorsOverWarnings_test(
|
|||||||
assert_that(
|
assert_that(
|
||||||
test_utils.VIM_MATCHES,
|
test_utils.VIM_MATCHES,
|
||||||
contains(
|
contains(
|
||||||
|
VimMatch( 'YcmErrorSection', '\%3l\%8c' ),
|
||||||
VimMatch( 'YcmWarningSection', '\%3l\%5c\_.\{-}\%3l\%7c' ),
|
VimMatch( 'YcmWarningSection', '\%3l\%5c\_.\{-}\%3l\%7c' ),
|
||||||
VimMatch( 'YcmWarningSection', '\%3l\%3c\_.\{-}\%3l\%9c' ),
|
VimMatch( 'YcmWarningSection', '\%3l\%3c\_.\{-}\%3l\%9c' )
|
||||||
VimMatch( 'YcmErrorSection', '\%3l\%8c' )
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Only the error sign is placed.
|
# Only the error sign is placed.
|
||||||
vim_command.assert_has_exact_calls( [
|
vim_command.assert_has_exact_calls( [
|
||||||
call( 'sign define ycm_dummy_sign' ),
|
|
||||||
call( 'sign place 3 name=ycm_dummy_sign line=3 buffer=5' ),
|
|
||||||
call( 'sign place 1 name=YcmError line=3 buffer=5' ),
|
call( 'sign place 1 name=YcmError line=3 buffer=5' ),
|
||||||
call( 'sign undefine ycm_dummy_sign' ),
|
|
||||||
call( 'sign unplace 3 buffer=5' )
|
|
||||||
] )
|
] )
|
||||||
|
|
||||||
# When moving the cursor on the diagnostics, the error is displayed to the
|
# When moving the cursor on the diagnostics, the error is displayed to the
|
||||||
@ -546,3 +542,22 @@ def YouCompleteMe_UpdateDiagnosticInterface_PrioritizeErrorsOverWarnings_test(
|
|||||||
call( "expected ';' after expression (FixIt)",
|
call( "expected ';' after expression (FixIt)",
|
||||||
truncate = True, warning = False )
|
truncate = True, warning = False )
|
||||||
] )
|
] )
|
||||||
|
|
||||||
|
vim_command.reset_mock()
|
||||||
|
with patch( 'ycm.client.event_notification.EventNotification.Response',
|
||||||
|
return_value = diagnostics[ 1 : ] ):
|
||||||
|
ycm.OnFileReadyToParse()
|
||||||
|
ycm.HandleFileParseRequest( block = True )
|
||||||
|
|
||||||
|
assert_that(
|
||||||
|
test_utils.VIM_MATCHES,
|
||||||
|
contains(
|
||||||
|
VimMatch( 'YcmWarningSection', '\%3l\%5c\_.\{-}\%3l\%7c' ),
|
||||||
|
VimMatch( 'YcmWarningSection', '\%3l\%3c\_.\{-}\%3l\%9c' )
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
vim_command.assert_has_exact_calls( [
|
||||||
|
call( 'sign place 2 name=YcmWarning line=3 buffer=5' ),
|
||||||
|
call( 'try | exec "sign unplace 1 buffer=5" | catch /E158/ | endtry' )
|
||||||
|
] )
|
||||||
|
@ -174,26 +174,6 @@ def PlaceSign( sign_id, line_num, buffer_num, is_error = True ):
|
|||||||
sign_id, sign_name, line_num, buffer_num ) )
|
sign_id, sign_name, line_num, buffer_num ) )
|
||||||
|
|
||||||
|
|
||||||
def PlaceDummySign( sign_id, buffer_num, line_num ):
|
|
||||||
if buffer_num < 0 or line_num < 0:
|
|
||||||
return
|
|
||||||
vim.command( 'sign define ycm_dummy_sign' )
|
|
||||||
vim.command(
|
|
||||||
'sign place {0} name=ycm_dummy_sign line={1} buffer={2}'.format(
|
|
||||||
sign_id,
|
|
||||||
line_num,
|
|
||||||
buffer_num,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def UnPlaceDummySign( sign_id, buffer_num ):
|
|
||||||
if buffer_num < 0:
|
|
||||||
return
|
|
||||||
vim.command( 'sign undefine ycm_dummy_sign' )
|
|
||||||
vim.command( 'sign unplace {0} buffer={1}'.format( sign_id, buffer_num ) )
|
|
||||||
|
|
||||||
|
|
||||||
def ClearYcmSyntaxMatches():
|
def ClearYcmSyntaxMatches():
|
||||||
matches = VimExpressionToPythonType( 'getmatches()' )
|
matches = VimExpressionToPythonType( 'getmatches()' )
|
||||||
for match in matches:
|
for match in matches:
|
||||||
@ -592,6 +572,11 @@ def CurrentFiletypes():
|
|||||||
return VimExpressionToPythonType( "&filetype" ).split( '.' )
|
return VimExpressionToPythonType( "&filetype" ).split( '.' )
|
||||||
|
|
||||||
|
|
||||||
|
def GetBufferFiletypes( bufnr ):
|
||||||
|
command = 'getbufvar({0}, "&ft")'.format( bufnr )
|
||||||
|
return VimExpressionToPythonType( command ).split( '.' )
|
||||||
|
|
||||||
|
|
||||||
def FiletypesForBuffer( buffer_object ):
|
def FiletypesForBuffer( buffer_object ):
|
||||||
# NOTE: Getting &ft for other buffers only works when the buffer has been
|
# NOTE: Getting &ft for other buffers only works when the buffer has been
|
||||||
# visited by the user at least once, which is true for modified buffers
|
# visited by the user at least once, which is true for modified buffers
|
||||||
|
Loading…
Reference in New Issue
Block a user