From 74021144c0e42e28745a9bfa5a89f8b6ad4baa50 Mon Sep 17 00:00:00 2001 From: Strahinja Val Markovic Date: Fri, 22 Mar 2013 10:22:50 -0700 Subject: [PATCH] Making the omni completer more robust - There was a bug in not calling int() on the result of the first call to the omnifunc. - We need to be more resilient to badly written omnifuncs and check that the result of the second call is a list or a dict with a list, as the vim docs say the omnifunc should return on the second call. One of the two fixes probably fixes #198 but since I can't repro the error, I can't be sure. --- python/completers/all/omni_completer.py | 38 +++++++++++++++++-------- 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/python/completers/all/omni_completer.py b/python/completers/all/omni_completer.py index 77a06e14..5e0436be 100644 --- a/python/completers/all/omni_completer.py +++ b/python/completers/all/omni_completer.py @@ -21,6 +21,10 @@ import vim import vimsupport from completers.completer import Completer +OMNIFUNC_RETURNED_BAD_VALUE = 'Omnifunc returned bad value to YCM!' +OMNIFUNC_NOT_LIST = ( 'Omnifunc did not return a list or a dict with a "words" ' + ' list when expected.' ) + class OmniCompleter( Completer ): def __init__( self ): super( OmniCompleter, self ).__init__() @@ -43,20 +47,30 @@ class OmniCompleter( Completer ): self.stored_candidates = None return - return_value = vim.eval( self.omnifunc + '(1,"")' ) - if return_value < 0: + try: + return_value = int( vim.eval( self.omnifunc + '(1,"")' ) ) + if return_value < 0: + self.stored_candidates = None + return + + omnifunc_call = [ self.omnifunc, + "(0,'", + vimsupport.EscapeForVim( query ), + "')" ] + + items = vim.eval( ''.join( omnifunc_call ) ) + if hasattr( items, 'words' ): + items = items.words + if not hasattr( items, '__iter__' ): + raise TypeError( OMNIFUNC_NOT_LIST ) + + self.stored_candidates = filter( bool, items ) + except (TypeError, ValueError) as error: + vimsupport.PostVimMessage( + OMNIFUNC_RETURNED_BAD_VALUE + ' ' + str( error ) ) self.stored_candidates = None return - omnifunc_call = [ self.omnifunc, - "(0,'", - vimsupport.EscapeForVim( query ), - "')" ] - - items = vim.eval( ''.join( omnifunc_call ) ) - if hasattr( items, 'words' ): - items = items.words - self.stored_candidates = filter( bool, items ) def AsyncCandidateRequestReadyInner( self ): @@ -68,5 +82,5 @@ class OmniCompleter( Completer ): def CandidatesFromStoredRequestInner( self ): - return self.stored_candidates + return self.stored_candidates if self.stored_candidates else []