From 6c326a1b5fcea6008e80d76bf46adb9169bd541c Mon Sep 17 00:00:00 2001 From: micbou Date: Thu, 8 Feb 2018 03:48:07 +0100 Subject: [PATCH] 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. --- python/ycm/tests/command_test.py | 21 +++++++++++++++++++-- python/ycm/tests/test_utils.py | 3 ++- python/ycm/tests/vimsupport_test.py | 3 --- python/ycm/youcompleteme.py | 13 +++++++++++-- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/python/ycm/tests/command_test.py b/python/ycm/tests/command_test.py index 6ad41992..cdb280c2 100644 --- a/python/ycm/tests/command_test.py +++ b/python/ycm/tests/command_test.py @@ -22,7 +22,7 @@ from __future__ import absolute_import # Not installing aliases from python-future; it's unreliable and slow. from builtins import * # noqa -from ycm.tests.test_utils import ( MockVimModule, MockVimBuffers, VimBuffer ) +from ycm.tests.test_utils import MockVimModule, MockVimBuffers, VimBuffer MockVimModule() from hamcrest import assert_that, equal_to @@ -32,7 +32,7 @@ from ycm.tests import YouCompleteMeInstance @YouCompleteMeInstance( { 'extra_conf_vim_data': [ 'tempname()' ] } ) -def SendCommandRequest_test( ycm ): +def SendCommandRequest_ExtraConfData_Works_test( ycm ): current_buffer = VimBuffer( 'buffer' ) with MockVimBuffers( [ current_buffer ], current_buffer ): with patch( 'ycm.youcompleteme.SendCommandRequest' ) as send_request: @@ -47,3 +47,20 @@ def SendCommandRequest_test( ycm ): ycm.SendCommandRequest( [ 'GoTo' ], 'python' ), 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' ) + ) diff --git a/python/ycm/tests/test_utils.py b/python/ycm/tests/test_utils.py index 797d69df..5fca82eb 100644 --- a/python/ycm/tests/test_utils.py +++ b/python/ycm/tests/test_utils.py @@ -215,7 +215,7 @@ def _MockVimEval( value ): if match: return match.group( 'filepath' ) - raise ValueError( 'Unexpected evaluation: {0}'.format( value ) ) + raise VimError( 'Unexpected evaluation: {0}'.format( value ) ) def _MockWipeoutBuffer( buffer_number ): @@ -381,6 +381,7 @@ def MockVimModule(): VIM_MOCK.buffers = {} VIM_MOCK.eval = MagicMock( side_effect = _MockVimEval ) + VIM_MOCK.error = VimError sys.modules[ 'vim' ] = VIM_MOCK return VIM_MOCK diff --git a/python/ycm/tests/vimsupport_test.py b/python/ycm/tests/vimsupport_test.py index 7c36c6a0..2e9a1a4d 100644 --- a/python/ycm/tests/vimsupport_test.py +++ b/python/ycm/tests/vimsupport_test.py @@ -1684,7 +1684,6 @@ def JumpToLocation_DifferentFile_SameBuffer_Modified_CanHide_test( @patch( 'ycmd.user_options_store._USER_OPTIONS', { 'goto_buffer_command': 'same-buffer' } ) -@patch( 'vim.error', VimError ) @patch( 'vim.command', side_effect = [ None, VimError( 'Unknown code' ), None ] ) 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', { 'goto_buffer_command': 'same-buffer' } ) -@patch( 'vim.error', VimError ) @patch( 'vim.command', new_callable = ExtendedMock, 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', { 'goto_buffer_command': 'same-buffer' } ) -@patch( 'vim.error', VimError ) @patch( 'vim.command', new_callable = ExtendedMock, side_effect = [ None, KeyboardInterrupt, None ] ) diff --git a/python/ycm/youcompleteme.py b/python/ycm/youcompleteme.py index 1a7ac2cb..6d78f2c0 100644 --- a/python/ycm/youcompleteme.py +++ b/python/ycm/youcompleteme.py @@ -750,8 +750,17 @@ class YouCompleteMe( object ): def _AddExtraConfDataIfNeeded( self, extra_data ): def BuildExtraConfData( extra_conf_vim_data ): - return dict( ( expr, vimsupport.VimExpressionToPythonType( expr ) ) - for expr in extra_conf_vim_data ) + extra_conf_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' ] if extra_conf_vim_data: