Avoid traceback when computing extra conf data

Evaluating the values of g:ycm_extra_conf_vim_data may raise a Python exception
(e.g. one of the values is not defined). Since that option is parsed each time
a request is sent, such exception makes the editor almost unusable as each key
press is printing a Python traceback to the user. Catch and log the exception.
This commit is contained in:
micbou 2018-02-08 03:48:07 +01:00
parent d0c6b6186e
commit 6c326a1b5f
No known key found for this signature in database
GPG Key ID: C7E8FD1F3BDA1E05
4 changed files with 32 additions and 8 deletions

View File

@ -22,7 +22,7 @@ from __future__ import absolute_import
# Not installing aliases from python-future; it's unreliable and slow. # Not installing aliases from python-future; it's unreliable and slow.
from builtins import * # noqa from builtins import * # noqa
from ycm.tests.test_utils import ( MockVimModule, MockVimBuffers, VimBuffer ) from ycm.tests.test_utils import MockVimModule, MockVimBuffers, VimBuffer
MockVimModule() MockVimModule()
from hamcrest import assert_that, equal_to from hamcrest import assert_that, equal_to
@ -32,7 +32,7 @@ from ycm.tests import YouCompleteMeInstance
@YouCompleteMeInstance( { 'extra_conf_vim_data': [ 'tempname()' ] } ) @YouCompleteMeInstance( { 'extra_conf_vim_data': [ 'tempname()' ] } )
def SendCommandRequest_test( ycm ): def SendCommandRequest_ExtraConfData_Works_test( ycm ):
current_buffer = VimBuffer( 'buffer' ) current_buffer = VimBuffer( 'buffer' )
with MockVimBuffers( [ current_buffer ], current_buffer ): with MockVimBuffers( [ current_buffer ], current_buffer ):
with patch( 'ycm.youcompleteme.SendCommandRequest' ) as send_request: with patch( 'ycm.youcompleteme.SendCommandRequest' ) as send_request:
@ -47,3 +47,20 @@ def SendCommandRequest_test( ycm ):
ycm.SendCommandRequest( [ 'GoTo' ], 'python' ), ycm.SendCommandRequest( [ 'GoTo' ], 'python' ),
equal_to( 'Some response' ) equal_to( 'Some response' )
) )
@YouCompleteMeInstance( { 'extra_conf_vim_data': [ 'undefined_value' ] } )
def SendCommandRequest_ExtraConfData_UndefinedValue_test( ycm ):
current_buffer = VimBuffer( 'buffer' )
with MockVimBuffers( [ current_buffer ], current_buffer ):
with patch( 'ycm.youcompleteme.SendCommandRequest' ) as send_request:
ycm.SendCommandRequest( [ 'GoTo' ], 'python' )
send_request.assert_called_once_with(
[ 'GoTo' ], 'python', { 'extra_conf_data': {} }
)
with patch( 'ycm.client.base_request.JsonFromFuture',
return_value = 'Some response' ):
assert_that(
ycm.SendCommandRequest( [ 'GoTo' ], 'python' ),
equal_to( 'Some response' )
)

View File

@ -215,7 +215,7 @@ def _MockVimEval( value ):
if match: if match:
return match.group( 'filepath' ) return match.group( 'filepath' )
raise ValueError( 'Unexpected evaluation: {0}'.format( value ) ) raise VimError( 'Unexpected evaluation: {0}'.format( value ) )
def _MockWipeoutBuffer( buffer_number ): def _MockWipeoutBuffer( buffer_number ):
@ -381,6 +381,7 @@ def MockVimModule():
VIM_MOCK.buffers = {} VIM_MOCK.buffers = {}
VIM_MOCK.eval = MagicMock( side_effect = _MockVimEval ) VIM_MOCK.eval = MagicMock( side_effect = _MockVimEval )
VIM_MOCK.error = VimError
sys.modules[ 'vim' ] = VIM_MOCK sys.modules[ 'vim' ] = VIM_MOCK
return VIM_MOCK return VIM_MOCK

View File

@ -1684,7 +1684,6 @@ def JumpToLocation_DifferentFile_SameBuffer_Modified_CanHide_test(
@patch( 'ycmd.user_options_store._USER_OPTIONS', @patch( 'ycmd.user_options_store._USER_OPTIONS',
{ 'goto_buffer_command': 'same-buffer' } ) { 'goto_buffer_command': 'same-buffer' } )
@patch( 'vim.error', VimError )
@patch( 'vim.command', @patch( 'vim.command',
side_effect = [ None, VimError( 'Unknown code' ), None ] ) side_effect = [ None, VimError( 'Unknown code' ), None ] )
def JumpToLocation_DifferentFile_SameBuffer_SwapFile_Unexpected_test( def JumpToLocation_DifferentFile_SameBuffer_SwapFile_Unexpected_test(
@ -1701,7 +1700,6 @@ def JumpToLocation_DifferentFile_SameBuffer_SwapFile_Unexpected_test(
@patch( 'ycmd.user_options_store._USER_OPTIONS', @patch( 'ycmd.user_options_store._USER_OPTIONS',
{ 'goto_buffer_command': 'same-buffer' } ) { 'goto_buffer_command': 'same-buffer' } )
@patch( 'vim.error', VimError )
@patch( 'vim.command', @patch( 'vim.command',
new_callable = ExtendedMock, new_callable = ExtendedMock,
side_effect = [ None, VimError( 'E325' ), None ] ) side_effect = [ None, VimError( 'E325' ), None ] )
@ -1720,7 +1718,6 @@ def JumpToLocation_DifferentFile_SameBuffer_SwapFile_Quit_test( vim_command ):
@patch( 'ycmd.user_options_store._USER_OPTIONS', @patch( 'ycmd.user_options_store._USER_OPTIONS',
{ 'goto_buffer_command': 'same-buffer' } ) { 'goto_buffer_command': 'same-buffer' } )
@patch( 'vim.error', VimError )
@patch( 'vim.command', @patch( 'vim.command',
new_callable = ExtendedMock, new_callable = ExtendedMock,
side_effect = [ None, KeyboardInterrupt, None ] ) side_effect = [ None, KeyboardInterrupt, None ] )

View File

@ -750,8 +750,17 @@ class YouCompleteMe( object ):
def _AddExtraConfDataIfNeeded( self, extra_data ): def _AddExtraConfDataIfNeeded( self, extra_data ):
def BuildExtraConfData( extra_conf_vim_data ): def BuildExtraConfData( extra_conf_vim_data ):
return dict( ( expr, vimsupport.VimExpressionToPythonType( expr ) ) extra_conf_data = {}
for expr in extra_conf_vim_data ) for expr in extra_conf_vim_data:
try:
extra_conf_data[ expr ] = vimsupport.VimExpressionToPythonType( expr )
except vim.error:
message = (
"Error evaluating '{expr}' in the 'g:ycm_extra_conf_vim_data' "
"option.".format( expr = expr ) )
vimsupport.PostVimMessage( message, truncate = True )
self._logger.exception( message )
return extra_conf_data
extra_conf_vim_data = self._user_options[ 'extra_conf_vim_data' ] extra_conf_vim_data = self._user_options[ 'extra_conf_vim_data' ]
if extra_conf_vim_data: if extra_conf_vim_data: