From 8c6efb42148e2e84f33b3510e6d0539dcf11b6a1 Mon Sep 17 00:00:00 2001 From: Davit Samvelyan Date: Sun, 4 Jun 2017 12:09:49 +0400 Subject: [PATCH] Cache current buffer on buffer visit. --- autoload/youcompleteme.vim | 7 +++- python/ycm/tests/event_notification_test.py | 30 ++++++++--------- python/ycm/tests/test_utils.py | 5 ++- python/ycm/tests/youcompleteme_test.py | 14 ++++---- python/ycm/youcompleteme.py | 37 +++++++++++---------- 5 files changed, 51 insertions(+), 42 deletions(-) diff --git a/autoload/youcompleteme.vim b/autoload/youcompleteme.vim index f7c99c88..673cbfa9 100644 --- a/autoload/youcompleteme.vim +++ b/autoload/youcompleteme.vim @@ -105,6 +105,9 @@ function! youcompleteme#Enable() autocmd CompleteDone * call s:OnCompleteDone() augroup END + " The BufEnter event is not triggered for the first loaded file. + exec s:python_command "ycm_state.SetCurrentBuffer()" + " The FileType event is not triggered for the first loaded file. We wait until " the server is ready to manually run the s:OnFileTypeSet function. let s:pollers.server_ready.id = timer_start( @@ -431,6 +434,8 @@ endfunction function! s:OnBufferEnter() + exec s:python_command "ycm_state.SetCurrentBuffer()" + if !s:VisitedBufferRequiresReparse() return endif @@ -460,7 +465,7 @@ endfunction function! s:PollServerReady( timer_id ) - if !s:Pyeval( 'ycm_state.IsServerReady()' ) + if !s:Pyeval( 'ycm_state.CheckIfServerIsReady()' ) let s:pollers.server_ready.id = timer_start( \ s:pollers.server_ready.wait_milliseconds, \ function( 's:PollServerReady' ) ) diff --git a/python/ycm/tests/event_notification_test.py b/python/ycm/tests/event_notification_test.py index f7cf5dfc..4b44447c 100644 --- a/python/ycm/tests/event_notification_test.py +++ b/python/ycm/tests/event_notification_test.py @@ -59,7 +59,7 @@ def UnplaceSign_Call( sign_id, buffer_num ): @contextlib.contextmanager -def MockArbitraryBuffer( filetype ): +def MockArbitraryBuffer( filetype, ycm ): """Used via the with statement, set up a single buffer with an arbitrary name and no contents. Its filetype is set to the supplied filetype.""" @@ -68,7 +68,7 @@ def MockArbitraryBuffer( filetype ): window = 1, filetype = filetype ) - with MockVimBuffers( [ current_buffer ], current_buffer ): + with MockVimBuffers( [ current_buffer ], current_buffer, ycm_state = ycm ): yield @@ -105,7 +105,7 @@ def MockEventNotification( response_method, native_filetype_completer = True ): 'ycm.youcompleteme.YouCompleteMe.FiletypeCompleterExistsForFiletype', return_value = native_filetype_completer ): - with patch( 'ycm.youcompleteme.YouCompleteMe.IsServerReadyWithCache', + with patch( 'ycm.youcompleteme.YouCompleteMe.IsServerReady', return_value = True ): yield @@ -124,7 +124,7 @@ def EventNotification_FileReadyToParse_NonDiagnostic_Error_test( def ErrorResponse( *args ): raise ServerError( ERROR_TEXT ) - with MockArbitraryBuffer( 'javascript' ): + with MockArbitraryBuffer( 'javascript', ycm ): with MockEventNotification( ErrorResponse ): ycm.OnFileReadyToParse() ok_( ycm.FileParseRequestReady() ) @@ -156,7 +156,7 @@ def EventNotification_FileReadyToParse_NonDiagnostic_Error_test( def EventNotification_FileReadyToParse_NonDiagnostic_Error_NonNative_test( ycm, vim_command ): - with MockArbitraryBuffer( 'javascript' ): + with MockArbitraryBuffer( 'javascript', ycm ): with MockEventNotification( None, False ): ycm.OnFileReadyToParse() ycm.HandleFileParseRequest() @@ -182,7 +182,7 @@ def EventNotification_FileReadyToParse_NonDiagnostic_ConfirmExtraConf_test( def UnknownExtraConfResponse( *args ): raise UnknownExtraConf( FILE_NAME ) - with MockArbitraryBuffer( 'javascript' ): + with MockArbitraryBuffer( 'javascript', ycm ): with MockEventNotification( UnknownExtraConfResponse ): # When the user accepts the extra conf, we load it @@ -282,7 +282,7 @@ def _Check_FileReadyToParse_Diagnostic_Error( ycm, vim_command ): diagnostic = Diagnostic( [], start, extent, 'expected ;', 'ERROR' ) return [ BuildDiagnosticData( diagnostic ) ] - with MockArbitraryBuffer( 'cpp' ): + with MockArbitraryBuffer( 'cpp', ycm ): with MockEventNotification( DiagnosticResponse ): ycm.OnFileReadyToParse() ok_( ycm.FileParseRequestReady() ) @@ -314,7 +314,7 @@ def _Check_FileReadyToParse_Diagnostic_Warning( ycm, vim_command ): diagnostic = Diagnostic( [], start, extent, 'cast', 'WARNING' ) return [ BuildDiagnosticData( diagnostic ) ] - with MockArbitraryBuffer( 'cpp' ): + with MockArbitraryBuffer( 'cpp', ycm ): with MockEventNotification( DiagnosticResponse ): ycm.OnFileReadyToParse() ok_( ycm.FileParseRequestReady() ) @@ -340,7 +340,7 @@ def _Check_FileReadyToParse_Diagnostic_Clean( ycm, vim_command ): # Tests Vim sign unplacement and error/warning count python API # when there are no errors/warnings left. # Should be called after _Check_FileReadyToParse_Diagnostic_Warning - with MockArbitraryBuffer( 'cpp' ): + with MockArbitraryBuffer( 'cpp', ycm ): with MockEventNotification( MagicMock( return_value = [] ) ): ycm.OnFileReadyToParse() ycm.HandleFileParseRequest() @@ -352,7 +352,7 @@ def _Check_FileReadyToParse_Diagnostic_Clean( ycm, vim_command ): @patch( 'ycm.youcompleteme.YouCompleteMe._AddUltiSnipsDataIfNeeded' ) -@patch( 'ycm.youcompleteme.YouCompleteMe.IsServerReadyWithCache', +@patch( 'ycm.youcompleteme.YouCompleteMe.IsServerReady', return_value = True ) @YouCompleteMeInstance( { 'collect_identifiers_from_tags_files': 1 } ) def EventNotification_FileReadyToParse_TagFiles_UnicodeWorkingDirectory_test( @@ -366,7 +366,7 @@ def EventNotification_FileReadyToParse_TagFiles_UnicodeWorkingDirectory_test( with patch( 'ycm.client.event_notification.EventNotification.' 'PostDataToHandlerAsync' ) as post_data_to_handler_async: with CurrentWorkingDirectory( unicode_dir ): - with MockVimBuffers( [ current_buffer ], current_buffer, ( 6, 5 ) ): + with MockVimBuffers( [ current_buffer ], current_buffer, ( 6, 5 ), ycm ): ycm.OnFileReadyToParse() assert_that( @@ -498,7 +498,7 @@ def EventNotification_BufferUnload_BuildRequestForDeletedAndUnsavedBuffers_test( @patch( 'ycm.syntax_parse.SyntaxKeywordsForCurrentBuffer', return_value = [ 'foo', 'bar' ] ) -@patch( 'ycm.youcompleteme.YouCompleteMe.IsServerReadyWithCache', +@patch( 'ycm.youcompleteme.YouCompleteMe.IsServerReady', return_value = True ) @YouCompleteMeInstance( { 'seed_identifiers_with_syntax': 1 } ) def EventNotification_FileReadyToParse_SyntaxKeywords_SeedWithCache_test( @@ -509,7 +509,7 @@ def EventNotification_FileReadyToParse_SyntaxKeywords_SeedWithCache_test( with patch( 'ycm.client.event_notification.EventNotification.' 'PostDataToHandlerAsync' ) as post_data_to_handler_async: - with MockVimBuffers( [ current_buffer ], current_buffer ): + with MockVimBuffers( [ current_buffer ], current_buffer, ycm_state = ycm ): ycm.OnFileReadyToParse() assert_that( # Positional arguments passed to PostDataToHandlerAsync. @@ -534,7 +534,7 @@ def EventNotification_FileReadyToParse_SyntaxKeywords_SeedWithCache_test( @patch( 'ycm.syntax_parse.SyntaxKeywordsForCurrentBuffer', return_value = [ 'foo', 'bar' ] ) -@patch( 'ycm.youcompleteme.YouCompleteMe.IsServerReadyWithCache', +@patch( 'ycm.youcompleteme.YouCompleteMe.IsServerReady', return_value = True ) @YouCompleteMeInstance( { 'seed_identifiers_with_syntax': 1 } ) def EventNotification_FileReadyToParse_SyntaxKeywords_ClearCacheIfRestart_test( @@ -545,7 +545,7 @@ def EventNotification_FileReadyToParse_SyntaxKeywords_ClearCacheIfRestart_test( with patch( 'ycm.client.event_notification.EventNotification.' 'PostDataToHandlerAsync' ) as post_data_to_handler_async: - with MockVimBuffers( [ current_buffer ], current_buffer ): + with MockVimBuffers( [ current_buffer ], current_buffer, ycm_state = ycm ): ycm.OnFileReadyToParse() assert_that( # Positional arguments passed to PostDataToHandlerAsync. diff --git a/python/ycm/tests/test_utils.py b/python/ycm/tests/test_utils.py index 03c5c56f..41adffcb 100644 --- a/python/ycm/tests/test_utils.py +++ b/python/ycm/tests/test_utils.py @@ -271,7 +271,8 @@ class VimMatch( object ): @contextlib.contextmanager -def MockVimBuffers( buffers, current_buffer, cursor_position = ( 1, 1 ) ): +def MockVimBuffers( buffers, current_buffer, cursor_position = ( 1, 1 ), + ycm_state = None): """Simulates the Vim buffers list |buffers| where |current_buffer| is the buffer displayed in the current window and |cursor_position| is the current cursor position. All buffers are represented by a VimBuffer object.""" @@ -281,6 +282,8 @@ def MockVimBuffers( buffers, current_buffer, cursor_position = ( 1, 1 ) ): with patch( 'vim.buffers', buffers ): with patch( 'vim.current.buffer', current_buffer ): with patch( 'vim.current.window.cursor', cursor_position ): + if ycm_state is not None: + ycm_state.SetCurrentBuffer() yield diff --git a/python/ycm/tests/youcompleteme_test.py b/python/ycm/tests/youcompleteme_test.py index a5570c7c..bca9c73f 100644 --- a/python/ycm/tests/youcompleteme_test.py +++ b/python/ycm/tests/youcompleteme_test.py @@ -330,7 +330,7 @@ def YouCompleteMe_ShowDiagnostics_NoDiagnosticsDetected_test( ycm, set_location_list, post_vim_message, *args ): current_buffer = VimBuffer( 'buffer', filetype = 'cpp' ) - with MockVimBuffers( [ current_buffer ], current_buffer ): + with MockVimBuffers( [ current_buffer ], current_buffer, ycm_state = ycm ): with patch( 'ycm.client.event_notification.EventNotification.Response', return_value = {} ): ycm.ShowDiagnostics() @@ -349,7 +349,7 @@ def YouCompleteMe_ShowDiagnostics_NoDiagnosticsDetected_test( 'open_loclist_on_ycm_diags': 0 } ) @patch( 'ycm.youcompleteme.YouCompleteMe.FiletypeCompleterExistsForFiletype', return_value = True ) -@patch( 'ycm.youcompleteme.YouCompleteMe.IsServerReadyWithCache', +@patch( 'ycm.youcompleteme.YouCompleteMe.IsServerReady', return_value = True ) @patch( 'ycm.vimsupport.PostVimMessage', new_callable = ExtendedMock ) @patch( 'ycm.vimsupport.SetLocationList', new_callable = ExtendedMock ) @@ -367,7 +367,7 @@ def YouCompleteMe_ShowDiagnostics_DiagnosticsFound_DoNotOpenLocationList_test( } current_buffer = VimBuffer( 'buffer', filetype = 'cpp', number = 3 ) - with MockVimBuffers( [ current_buffer ], current_buffer ): + with MockVimBuffers( [ current_buffer ], current_buffer, ycm_state = ycm ): with patch( 'ycm.client.event_notification.EventNotification.Response', return_value = [ diagnostic ] ): ycm.ShowDiagnostics() @@ -390,7 +390,7 @@ def YouCompleteMe_ShowDiagnostics_DiagnosticsFound_DoNotOpenLocationList_test( @YouCompleteMeInstance( { 'open_loclist_on_ycm_diags': 1 } ) @patch( 'ycm.youcompleteme.YouCompleteMe.FiletypeCompleterExistsForFiletype', return_value = True ) -@patch( 'ycm.youcompleteme.YouCompleteMe.IsServerReadyWithCache', +@patch( 'ycm.youcompleteme.YouCompleteMe.IsServerReady', return_value = True ) @patch( 'ycm.vimsupport.PostVimMessage', new_callable = ExtendedMock ) @patch( 'ycm.vimsupport.SetLocationList', new_callable = ExtendedMock ) @@ -409,7 +409,7 @@ def YouCompleteMe_ShowDiagnostics_DiagnosticsFound_OpenLocationList_test( } current_buffer = VimBuffer( 'buffer', filetype = 'cpp', number = 3 ) - with MockVimBuffers( [ current_buffer ], current_buffer ): + with MockVimBuffers( [ current_buffer ], current_buffer, ycm_state = ycm ): with patch( 'ycm.client.event_notification.EventNotification.Response', return_value = [ diagnostic ] ): ycm.ShowDiagnostics() @@ -435,7 +435,7 @@ def YouCompleteMe_ShowDiagnostics_DiagnosticsFound_OpenLocationList_test( 'enable_diagnostic_highlighting': 1 } ) @patch( 'ycm.youcompleteme.YouCompleteMe.FiletypeCompleterExistsForFiletype', return_value = True ) -@patch( 'ycm.youcompleteme.YouCompleteMe.IsServerReadyWithCache', +@patch( 'ycm.youcompleteme.YouCompleteMe.IsServerReady', return_value = True ) @patch( 'ycm.vimsupport.PostVimMessage', new_callable = ExtendedMock ) @patch( 'vim.command', new_callable = ExtendedMock ) @@ -514,7 +514,7 @@ def YouCompleteMe_UpdateDiagnosticInterface_PrioritizeErrorsOverWarnings_test( test_utils.VIM_MATCHES = [] - with MockVimBuffers( [ current_buffer ], current_buffer, ( 3, 1 ) ): + with MockVimBuffers( [ current_buffer ], current_buffer, ( 3, 1 ), ycm ): with patch( 'ycm.client.event_notification.EventNotification.Response', return_value = diagnostics ): ycm.OnFileReadyToParse() diff --git a/python/ycm/youcompleteme.py b/python/ycm/youcompleteme.py index 2a6f667c..8eb3bfe5 100644 --- a/python/ycm/youcompleteme.py +++ b/python/ycm/youcompleteme.py @@ -115,6 +115,7 @@ class YouCompleteMe( object ): self._user_notified_about_crash = False self._omnicomp = OmniCompleter( user_options ) self._buffers = BufferDict( user_options ) + self._current_buffer = None self._latest_completion_request = None self._logger = logging.getLogger( 'ycm' ) self._client_logfile = None @@ -132,10 +133,6 @@ class YouCompleteMe( object ): } - def _GetCurrentBuffer( self ): - return self._buffers[ vimsupport.GetCurrentBufferNumber() ] - - def _SetupServer( self ): self._available_completers = {} self._user_notified_about_crash = False @@ -224,7 +221,7 @@ class YouCompleteMe( object ): return return_code is None - def IsServerReady( self ): + def CheckIfServerIsReady( self ): if not self._server_is_ready_with_cache and self.IsServerAlive(): with HandleServerException( display = False ): self._server_is_ready_with_cache = BaseRequest.GetDataFromHandler( @@ -232,7 +229,7 @@ class YouCompleteMe( object ): return self._server_is_ready_with_cache - def IsServerReadyWithCache( self ): + def IsServerReady( self ): return self._server_is_ready_with_cache @@ -360,7 +357,7 @@ class YouCompleteMe( object ): def NeedsReparse( self ): - return self._GetCurrentBuffer().NeedsReparse() + return self._current_buffer.NeedsReparse() def OnFileReadyToParse( self ): @@ -368,7 +365,7 @@ class YouCompleteMe( object ): self._NotifyUserIfServerCrashed() return - if not self.IsServerReadyWithCache(): + if not self.IsServerReady(): return self._omnicomp.OnFileReadyToParse( None ) @@ -378,7 +375,7 @@ class YouCompleteMe( object ): self._AddSyntaxDataIfNeeded( extra_data ) self._AddExtraConfDataIfNeeded( extra_data ) - self._GetCurrentBuffer().SendParseRequest( extra_data ) + self._current_buffer.SendParseRequest( extra_data ) def OnBufferUnload( self, deleted_buffer_file ): @@ -391,12 +388,16 @@ class YouCompleteMe( object ): SendEventNotificationAsync( 'BufferVisit', extra_data = extra_data ) + def SetCurrentBuffer( self ): + self._current_buffer = self._buffers[ vimsupport.GetCurrentBufferNumber() ] + + def OnInsertLeave( self ): SendEventNotificationAsync( 'InsertLeave' ) def OnCursorMoved( self ): - self._GetCurrentBuffer().OnCursorMoved() + self._current_buffer.OnCursorMoved() def _CleanLogfile( self ): @@ -523,11 +524,11 @@ class YouCompleteMe( object ): def GetErrorCount( self ): - return self._GetCurrentBuffer().GetErrorCount() + return self._current_buffer.GetErrorCount() def GetWarningCount( self ): - return self._GetCurrentBuffer().GetWarningCount() + return self._current_buffer.GetWarningCount() def DiagnosticUiSupportedForCurrentFiletype( self ): @@ -541,20 +542,20 @@ class YouCompleteMe( object ): def _PopulateLocationListWithLatestDiagnostics( self ): - return self._GetCurrentBuffer().PopulateLocationList() + return self._current_buffer.PopulateLocationList() def FileParseRequestReady( self ): # Return True if server is not ready yet, to stop repeating check timer. - return ( not self.IsServerReadyWithCache() or - self._GetCurrentBuffer().FileParseRequestReady() ) + return ( not self.IsServerReady() or + self._current_buffer.FileParseRequestReady() ) def HandleFileParseRequest( self, block = False ): - if not self.IsServerReadyWithCache(): + if not self.IsServerReady(): return - current_buffer = self._GetCurrentBuffer() + current_buffer = self._current_buffer # Order is important here: # FileParseRequestReady has a low cost, while # NativeFiletypeCompletionUsable is a blocking server request @@ -717,7 +718,7 @@ class YouCompleteMe( object ): if filetype in self._filetypes_with_keywords_loaded: return - if self.IsServerReadyWithCache(): + if self.IsServerReady(): self._filetypes_with_keywords_loaded.add( filetype ) extra_data[ 'syntax_keywords' ] = list( syntax_parse.SyntaxKeywordsForCurrentBuffer() )