Browse Source

Cache current buffer on buffer visit.

Davit Samvelyan 7 years ago
parent
commit
8c6efb4214

+ 6 - 1
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' ) )

+ 15 - 15
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.

+ 4 - 1
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
 
 

+ 7 - 7
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()

+ 19 - 18
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() )