Auto merge of #2797 - micbou:echo-diagnostic-async, r=Valloric

[READY] Echo diagnostic asynchronously

If there is a diagnostic on the current line while updating diagnostics, echo it on the command line. Here's a demo:

![echo-diagnostic-async](https://user-images.githubusercontent.com/10026824/31182114-4e784200-a923-11e7-831b-e613d126fd8b.gif)

Without this change, users have to move the cursor up and down to see the message on the command line.

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/valloric/youcompleteme/2797)
<!-- Reviewable:end -->
This commit is contained in:
zzbot 2017-10-04 11:30:50 -07:00 committed by GitHub
commit b5c8e57962
3 changed files with 43 additions and 13 deletions

View File

@ -38,17 +38,15 @@ class DiagnosticInterface( object ):
self._line_to_diags = defaultdict( list ) self._line_to_diags = defaultdict( list )
self._placed_signs = [] self._placed_signs = []
self._next_sign_id = 1 self._next_sign_id = 1
self._previous_line_number = -1 self._previous_diag_line_number = -1
self._diag_message_needs_clearing = False self._diag_message_needs_clearing = False
def OnCursorMoved( self ): def OnCursorMoved( self ):
if self._user_options[ 'echo_current_diagnostic' ]:
line, _ = vimsupport.CurrentLineAndColumn() line, _ = vimsupport.CurrentLineAndColumn()
line += 1 # Convert to 1-based line += 1 # Convert to 1-based
if line != self._previous_line_number: if line != self._previous_diag_line_number:
self._previous_line_number = line
if self._user_options[ 'echo_current_diagnostic' ]:
self._EchoDiagnosticForLine( line ) self._EchoDiagnosticForLine( line )
@ -72,6 +70,9 @@ class DiagnosticInterface( object ):
self._ApplyDiagnosticFilter( diags ) ] self._ApplyDiagnosticFilter( diags ) ]
self._ConvertDiagListToDict() self._ConvertDiagListToDict()
if self._user_options[ 'echo_current_diagnostic' ]:
self._EchoDiagnostic()
if self._user_options[ 'enable_diagnostic_signs' ]: if self._user_options[ 'enable_diagnostic_signs' ]:
self._UpdateSigns() self._UpdateSigns()
@ -88,7 +89,15 @@ class DiagnosticInterface( object ):
return filter( diag_filter.IsAllowed, diags ) return filter( diag_filter.IsAllowed, diags )
def _EchoDiagnostic( self ):
line, _ = vimsupport.CurrentLineAndColumn()
line += 1 # Convert to 1-based
self._EchoDiagnosticForLine( line )
def _EchoDiagnosticForLine( self, line_num ): def _EchoDiagnosticForLine( self, line_num ):
self._previous_diag_line_number = line_num
diags = self._line_to_diags[ line_num ] diags = self._line_to_diags[ line_num ]
if not diags: if not diags:
if self._diag_message_needs_clearing: if self._diag_message_needs_clearing:
@ -163,6 +172,9 @@ class DiagnosticInterface( object ):
new_signs = [] new_signs = []
obsolete_signs = list( self._placed_signs ) obsolete_signs = list( self._placed_signs )
for line, diags in iteritems( self._line_to_diags ): for line, diags in iteritems( self._line_to_diags ):
if not diags:
continue
# We always go for the first diagnostic on line, # We always go for the first diagnostic on line,
# because it is sorted giving priority to the Errors. # because it is sorted giving priority to the Errors.
diag = diags[ 0 ] diag = diags[ 0 ]

View File

@ -44,6 +44,7 @@ DEFAULT_CLIENT_OPTIONS = {
'keep_logfiles': 0, 'keep_logfiles': 0,
'extra_conf_vim_data': [], 'extra_conf_vim_data': [],
'show_diagnostics_ui': 1, 'show_diagnostics_ui': 1,
'echo_current_diagnostic': 1,
'enable_diagnostic_signs': 1, 'enable_diagnostic_signs': 1,
'enable_diagnostic_highlighting': 0, 'enable_diagnostic_highlighting': 0,
'always_populate_location_list': 0, 'always_populate_location_list': 0,

View File

@ -551,6 +551,11 @@ def YouCompleteMe_UpdateDiagnosticInterface_PrioritizeErrorsOverWarnings_test(
ycm.OnFileReadyToParse() ycm.OnFileReadyToParse()
ycm.HandleFileParseRequest( block = True ) ycm.HandleFileParseRequest( block = True )
# The error on the current line is echoed, not the warning.
post_vim_message.assert_called_once_with(
"expected ';' after expression (FixIt)",
truncate = True, warning = False )
# Error match is added after warning matches. # Error match is added after warning matches.
assert_that( assert_that(
test_utils.VIM_MATCHES, test_utils.VIM_MATCHES,
@ -566,13 +571,25 @@ def YouCompleteMe_UpdateDiagnosticInterface_PrioritizeErrorsOverWarnings_test(
call( 'sign place 1 name=YcmError line=3 buffer=5' ), call( 'sign place 1 name=YcmError line=3 buffer=5' ),
] ) ] )
# When moving the cursor on the diagnostics, the error is displayed to the # The error is not echoed again when moving the cursor along the line.
# user, not the warning. with MockVimBuffers( [ current_buffer ], current_buffer, ( 3, 2 ) ):
post_vim_message.reset_mock()
ycm.OnCursorMoved() ycm.OnCursorMoved()
post_vim_message.assert_has_exact_calls( [ post_vim_message.assert_not_called()
call( "expected ';' after expression (FixIt)",
# The error is cleared when moving the cursor to another line.
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 ) ):
post_vim_message.reset_mock()
ycm.OnCursorMoved()
post_vim_message.assert_called_once_with(
"expected ';' after expression (FixIt)",
truncate = True, warning = False ) truncate = True, warning = False )
] )
vim_command.reset_mock() vim_command.reset_mock()
with patch( 'ycm.client.event_notification.EventNotification.Response', with patch( 'ycm.client.event_notification.EventNotification.Response',