Merge branch 'seletskiy-master2'
This commit is contained in:
commit
b9f717f23b
@ -17,7 +17,7 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict, namedtuple
|
||||||
from ycm import vimsupport
|
from ycm import vimsupport
|
||||||
import vim
|
import vim
|
||||||
|
|
||||||
@ -31,6 +31,7 @@ class DiagnosticInterface( object ):
|
|||||||
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 ):
|
||||||
@ -47,8 +48,10 @@ class DiagnosticInterface( object ):
|
|||||||
self._buffer_number_to_line_to_diags = _ConvertDiagListToDict( diags )
|
self._buffer_number_to_line_to_diags = _ConvertDiagListToDict( diags )
|
||||||
|
|
||||||
if self._user_options[ 'enable_diagnostic_signs' ]:
|
if self._user_options[ 'enable_diagnostic_signs' ]:
|
||||||
self._next_sign_id = _UpdateSigns( self._buffer_number_to_line_to_diags,
|
self._placed_signs, self._next_sign_id = _UpdateSigns(
|
||||||
self._next_sign_id )
|
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 )
|
_UpdateSquiggles( self._buffer_number_to_line_to_diags )
|
||||||
@ -102,21 +105,81 @@ def _UpdateSquiggles( buffer_number_to_line_to_diags ):
|
|||||||
is_error = is_error )
|
is_error = is_error )
|
||||||
|
|
||||||
|
|
||||||
def _UpdateSigns( buffer_number_to_line_to_diags, next_sign_id ):
|
def _UpdateSigns( placed_signs, buffer_number_to_line_to_diags, next_sign_id ):
|
||||||
vimsupport.UnplaceAllSignsInBuffer( vim.current.buffer.number )
|
new_signs, kept_signs, next_sign_id = _GetKeptAndNewSigns(
|
||||||
|
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:
|
||||||
|
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.
|
||||||
|
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,
|
||||||
|
next_sign_id ):
|
||||||
|
new_signs = []
|
||||||
|
kept_signs = []
|
||||||
for buffer_number, line_to_diags in buffer_number_to_line_to_diags.iteritems():
|
for buffer_number, line_to_diags in buffer_number_to_line_to_diags.iteritems():
|
||||||
if not vimsupport.BufferIsVisible( buffer_number ):
|
if not vimsupport.BufferIsVisible( buffer_number ):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
vimsupport.UnplaceAllSignsInBuffer( buffer_number )
|
|
||||||
for line, diags in line_to_diags.iteritems():
|
for line, diags in line_to_diags.iteritems():
|
||||||
for diag in diags:
|
for diag in diags:
|
||||||
vimsupport.PlaceSign( next_sign_id,
|
sign = _DiagSignPlacement( next_sign_id,
|
||||||
line,
|
line,
|
||||||
buffer_number,
|
buffer_number,
|
||||||
_DiagnosticIsError( diag ) )
|
_DiagnosticIsError( diag ) )
|
||||||
next_sign_id += 1
|
if sign not in placed_signs:
|
||||||
return next_sign_id
|
new_signs += [ sign ]
|
||||||
|
next_sign_id += 1
|
||||||
|
else:
|
||||||
|
# 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 += [ placed_signs[ placed_signs.index( sign ) ] ]
|
||||||
|
return new_signs, kept_signs, next_sign_id
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _PlaceNewSigns( kept_signs, new_signs ):
|
||||||
|
placed_signs = kept_signs
|
||||||
|
for sign in new_signs:
|
||||||
|
# Do not set two signs on the same line, it will screw up storing sign
|
||||||
|
# locations.
|
||||||
|
if sign in placed_signs:
|
||||||
|
continue
|
||||||
|
vimsupport.PlaceSign( sign.id, sign.line, sign.buffer, sign.is_error )
|
||||||
|
placed_signs += [ sign ]
|
||||||
|
return placed_signs
|
||||||
|
|
||||||
|
|
||||||
|
def _UnplaceObsoleteSigns( kept_signs, placed_signs ):
|
||||||
|
for sign in placed_signs:
|
||||||
|
if sign not in kept_signs:
|
||||||
|
vimsupport.UnplaceSignInBuffer( sign.buffer, sign.id )
|
||||||
|
|
||||||
|
|
||||||
def _ConvertDiagListToDict( diag_list ):
|
def _ConvertDiagListToDict( diag_list ):
|
||||||
@ -140,3 +203,12 @@ def _ConvertDiagListToDict( diag_list ):
|
|||||||
def _DiagnosticIsError( diag ):
|
def _DiagnosticIsError( diag ):
|
||||||
return diag[ 'kind' ] == 'ERROR'
|
return diag[ 'kind' ] == 'ERROR'
|
||||||
|
|
||||||
|
|
||||||
|
class _DiagSignPlacement( namedtuple( "_DiagSignPlacement",
|
||||||
|
[ 'id', 'line', 'buffer', 'is_error' ] ) ):
|
||||||
|
# We want two signs that have different ids but the same location to compare
|
||||||
|
# equal. ID doesn't matter.
|
||||||
|
def __eq__( self, other ):
|
||||||
|
return ( self.line == other.line and
|
||||||
|
self.buffer == other.buffer and
|
||||||
|
self.is_error == other.is_error )
|
||||||
|
@ -137,16 +137,12 @@ def GetBufferFilepath( buffer_object ):
|
|||||||
return os.path.join( folder_path, str( buffer_object.number ) )
|
return os.path.join( folder_path, str( buffer_object.number ) )
|
||||||
|
|
||||||
|
|
||||||
# NOTE: This unplaces *all* signs in a buffer, not just the ones we placed. We
|
def UnplaceSignInBuffer( buffer_number, sign_id ):
|
||||||
# used to track which signs we ended up placing and would then only unplace
|
|
||||||
# ours, but that causes flickering Vim since we have to call
|
|
||||||
# sign unplace <id> buffer=<buffer-num>
|
|
||||||
# in a loop. So we're forced to unplace all signs, which might conflict with
|
|
||||||
# other Vim plugins.
|
|
||||||
def UnplaceAllSignsInBuffer( buffer_number ):
|
|
||||||
if buffer_number < 0:
|
if buffer_number < 0:
|
||||||
return
|
return
|
||||||
vim.command( 'sign unplace * buffer={0}'.format( buffer_number ) )
|
vim.command(
|
||||||
|
'try | exec "sign unplace {0} buffer={1}" | catch /E158/ | endtry'.format(
|
||||||
|
sign_id, buffer_number ) )
|
||||||
|
|
||||||
|
|
||||||
def PlaceSign( sign_id, line_num, buffer_num, is_error = True ):
|
def PlaceSign( sign_id, line_num, buffer_num, is_error = True ):
|
||||||
@ -160,6 +156,26 @@ def PlaceSign( sign_id, line_num, buffer_num, is_error = True ):
|
|||||||
sign_id, line_num, sign_name, buffer_num ) )
|
sign_id, line_num, sign_name, 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:
|
||||||
|
Loading…
Reference in New Issue
Block a user