fixup! To determine which completion prompted CompleteDone, look at the new variable if vim is recent enough.

This commit is contained in:
Spencer G. Jones 2015-09-10 09:18:48 -06:00
parent af4aaa1d17
commit 28e318c0bb
4 changed files with 140 additions and 107 deletions

View File

@ -1367,11 +1367,12 @@ Default: `0`
### The `g:ycm_csharp_insert_namespace_expr` option
When YCM inserts a namespace, by default, it will insert it under the nearest
using statement. When this option is set, YCM will instead set the global
variable `g:ycm_namespace_to_insert` to the namespace to insert, and then
evaluate this option's value as an expression. The expression is responsible
for inserting the namespace.
If you desired to control where YCM inserts namespaces, set this option. When
YCM inserts a namespace, by default, it will insert the namespace under the
nearest using statement. When this option is set, YCM will instead set the
global variable `g:ycm_namespace_to_insert` to the namespace to insert, and
then evaluate this option's value as an expression. The expression is
responsible for inserting the namespace.
Default: `''`

View File

@ -1584,11 +1584,12 @@ Default: '0'
-------------------------------------------------------------------------------
The *g:ycm_csharp_insert_namespace_expr* option
When YCM inserts a namespace, by default, it will insert it under the nearest
using statement. When this option is set, YCM will instead set the global
variable 'g:ycm_namespace_to_insert' to the namespace to insert, and then
evaluate this option's value as an expression. The expression is responsible
for inserting the namespace.
If you desired to control where YCM inserts namespaces, set this option. When
YCM inserts a namespace, by default, it will insert the namespace under the
nearest using statement. When this option is set, YCM will instead set the
global variable 'g:ycm_namespace_to_insert' to the namespace to insert, and
then evaluate this option's value as an expression. The expression is
responsible for inserting the namespace.
Default: "''"
>

View File

@ -60,7 +60,7 @@ def FilterToCompletedCompletions_NewVim_MatchIsReturned_test():
vimsupport.GetVariableValue = GetVariableValue_CompleteItemIs( "Test" )
completions = [ _BuildCompletion( "Test" ) ]
result = ycm_state.FilterToCompletedCompletions( completions, False )
result = ycm_state._FilterToMatchingCompletions( completions, False )
eq_( list( result ), completions )
@ -71,7 +71,7 @@ def FilterToCompletedCompletions_NewVim_ShortTextDoesntRaise_test():
vimsupport.GetVariableValue = GetVariableValue_CompleteItemIs( "A" )
completions = [ _BuildCompletion( "AAA" ) ]
ycm_state.FilterToCompletedCompletions( completions, False )
ycm_state._FilterToMatchingCompletions( completions, False )
def FilterToCompletedCompletions_NewVim_ExactMatchIsReturned_test():
@ -80,7 +80,7 @@ def FilterToCompletedCompletions_NewVim_ExactMatchIsReturned_test():
vimsupport.GetVariableValue = GetVariableValue_CompleteItemIs( "Test" )
completions = [ _BuildCompletion( "Test" ) ]
result = ycm_state.FilterToCompletedCompletions( completions, False )
result = ycm_state._FilterToMatchingCompletions( completions, False )
eq_( list( result ), completions )
@ -91,7 +91,7 @@ def FilterToCompletedCompletions_NewVim_NonMatchIsntReturned_test():
vimsupport.GetVariableValue = GetVariableValue_CompleteItemIs( " Quote" )
completions = [ _BuildCompletion( "A" ) ]
result = ycm_state.FilterToCompletedCompletions( completions, False )
result = ycm_state._FilterToMatchingCompletions( completions, False )
assert_that( list( result ), empty() )
@ -102,7 +102,7 @@ def FilterToCompletedCompletions_OldVim_MatchIsReturned_test():
vimsupport.TextBeforeCursor = MagicMock( return_value = " Test" )
completions = [ _BuildCompletion( "Test" ) ]
result = ycm_state.FilterToCompletedCompletions( completions, False )
result = ycm_state._FilterToMatchingCompletions( completions, False )
eq_( list( result ), completions )
@ -113,7 +113,7 @@ def FilterToCompletedCompletions_OldVim_ShortTextDoesntRaise_test():
vimsupport.TextBeforeCursor = MagicMock( return_value = "X" )
completions = [ _BuildCompletion( "AAA" ) ]
ycm_state.FilterToCompletedCompletions( completions, False )
ycm_state._FilterToMatchingCompletions( completions, False )
def FilterToCompletedCompletions_OldVim_ExactMatchIsReturned_test():
@ -122,7 +122,7 @@ def FilterToCompletedCompletions_OldVim_ExactMatchIsReturned_test():
vimsupport.TextBeforeCursor = MagicMock( return_value = "Test" )
completions = [ _BuildCompletion( "Test" ) ]
result = ycm_state.FilterToCompletedCompletions( completions, False )
result = ycm_state._FilterToMatchingCompletions( completions, False )
eq_( list( result ), completions )
@ -133,7 +133,7 @@ def FilterToCompletedCompletions_OldVim_NonMatchIsntReturned_test():
vimsupport.TextBeforeCursor = MagicMock( return_value = " Quote" )
completions = [ _BuildCompletion( "A" ) ]
result = ycm_state.FilterToCompletedCompletions( completions, False )
result = ycm_state._FilterToMatchingCompletions( completions, False )
assert_that( list( result ), empty() )
@ -144,7 +144,7 @@ def HasCompletionsThatCouldBeCompletedWithMoreText_OldVim_MatchIsReturned_test()
vimsupport.TextBeforeCursor = MagicMock( return_value = " Te" )
completions = [ _BuildCompletion( "Test" ) ]
result = ycm_state.HasCompletionsThatCouldBeCompletedWithMoreText( completions )
result = ycm_state._HasCompletionsThatCouldBeCompletedWithMoreText( completions )
eq_( result, True )
@ -155,7 +155,7 @@ def HasCompletionsThatCouldBeCompletedWithMoreText_OldVim_ShortTextDoesntRaise_t
vimsupport.TextBeforeCursor = MagicMock( return_value = "X" )
completions = [ _BuildCompletion( "AAA" ) ]
ycm_state.HasCompletionsThatCouldBeCompletedWithMoreText( completions )
ycm_state._HasCompletionsThatCouldBeCompletedWithMoreText( completions )
def HasCompletionsThatCouldBeCompletedWithMoreText_OldVim_ExactMatchIsntReturned_test():
@ -164,7 +164,7 @@ def HasCompletionsThatCouldBeCompletedWithMoreText_OldVim_ExactMatchIsntReturned
vimsupport.TextBeforeCursor = MagicMock( return_value = "Test" )
completions = [ _BuildCompletion( "Test" ) ]
result = ycm_state.HasCompletionsThatCouldBeCompletedWithMoreText( completions )
result = ycm_state._HasCompletionsThatCouldBeCompletedWithMoreText( completions )
eq_( result, False )
@ -175,7 +175,7 @@ def HasCompletionsThatCouldBeCompletedWithMoreText_OldVim_NonMatchIsntReturned_t
vimsupport.TextBeforeCursor = MagicMock( return_value = " Quote" )
completions = [ _BuildCompletion( "A" ) ]
result = ycm_state.HasCompletionsThatCouldBeCompletedWithMoreText( completions )
result = ycm_state._HasCompletionsThatCouldBeCompletedWithMoreText( completions )
eq_( result, False )
@ -186,7 +186,7 @@ def HasCompletionsThatCouldBeCompletedWithMoreText_NewVim_MatchIsReturned_test()
vimsupport.GetVariableValue = GetVariableValue_CompleteItemIs( "Te" )
completions = [ _BuildCompletion( "Test" ) ]
result = ycm_state.HasCompletionsThatCouldBeCompletedWithMoreText( completions )
result = ycm_state._HasCompletionsThatCouldBeCompletedWithMoreText( completions )
eq_( result, True )
@ -197,7 +197,7 @@ def HasCompletionsThatCouldBeCompletedWithMoreText_NewVim_ShortTextDoesntRaise_t
vimsupport.GetVariableValue = GetVariableValue_CompleteItemIs( "X" )
completions = [ _BuildCompletion( "AAA" ) ]
ycm_state.HasCompletionsThatCouldBeCompletedWithMoreText( completions )
ycm_state._HasCompletionsThatCouldBeCompletedWithMoreText( completions )
def HasCompletionsThatCouldBeCompletedWithMoreText_NewVim_ExactMatchIsntReturned_test():
@ -206,7 +206,7 @@ def HasCompletionsThatCouldBeCompletedWithMoreText_NewVim_ExactMatchIsntReturned
vimsupport.GetVariableValue = GetVariableValue_CompleteItemIs( "Test" )
completions = [ _BuildCompletion( "Test" ) ]
result = ycm_state.HasCompletionsThatCouldBeCompletedWithMoreText( completions )
result = ycm_state._HasCompletionsThatCouldBeCompletedWithMoreText( completions )
eq_( result, False )
@ -217,7 +217,7 @@ def HasCompletionsThatCouldBeCompletedWithMoreText_NewVim_NonMatchIsntReturned_t
vimsupport.GetVariableValue = GetVariableValue_CompleteItemIs( " Quote" )
completions = [ _BuildCompletion( "A" ) ]
result = ycm_state.HasCompletionsThatCouldBeCompletedWithMoreText( completions )
result = ycm_state._HasCompletionsThatCouldBeCompletedWithMoreText( completions )
eq_( result, False )
@ -225,54 +225,54 @@ def HasCompletionsThatCouldBeCompletedWithMoreText_NewVim_NonMatchIsntReturned_t
def GetRequiredNamespaceImport_ReturnNoneForNoExtraData_test():
ycm_state = YouCompleteMe( MagicMock( spec_set = dict ) )
eq_( None, ycm_state.GetRequiredNamespaceImport( {} ) )
eq_( None, ycm_state._GetRequiredNamespaceImport( {} ) )
def GetRequiredNamespaceImport_ReturnNamespaceFromExtraData_test():
namespace = "A_NAMESPACE"
ycm_state = YouCompleteMe( MagicMock( spec_set = dict ) )
eq_( namespace, ycm_state.GetRequiredNamespaceImport(
eq_( namespace, ycm_state._GetRequiredNamespaceImport(
_BuildCompletion( namespace )
))
def GetCompletedCompletions_ReturnEmptyIfNotDone_test():
def GetCompletionsUserMayHaveCompleted_ReturnEmptyIfNotDone_test():
ycm_state = _SetupForCsharpCompletionDone( [] )
ycm_state._latest_completion_request.Done = MagicMock( return_value = False )
eq_( [], ycm_state.GetCompletedCompletions() )
eq_( [], ycm_state.GetCompletionsUserMayHaveCompleted() )
def GetCompletedCompletions_ReturnEmptyIfPendingMatches_NewVim_test():
def GetCompletionsUserMayHaveCompleted_ReturnEmptyIfPendingMatches_NewVim_test():
completions = [ _BuildCompletion( None ) ]
ycm_state = _SetupForCsharpCompletionDone( completions )
vimsupport.VimVersionAtLeast = MagicMock( return_value = True )
vimsupport.GetVariableValue = GetVariableValue_CompleteItemIs( "Te" )
eq_( [], ycm_state.GetCompletedCompletions() )
eq_( [], ycm_state.GetCompletionsUserMayHaveCompleted() )
def GetCompletedCompletions_ReturnEmptyIfPendingMatches_OldVim_test():
def GetCompletionsUserMayHaveCompleted_ReturnEmptyIfPendingMatches_OldVim_test():
completions = [ _BuildCompletion( None ) ]
ycm_state = _SetupForCsharpCompletionDone( completions )
vimsupport.VimVersionAtLeast = MagicMock( return_value = False )
vimsupport.TextBeforeCursor = MagicMock( return_value = " Te" )
eq_( [], ycm_state.GetCompletedCompletions() )
eq_( [], ycm_state.GetCompletionsUserMayHaveCompleted() )
def GetCompletedCompletions_ReturnMatchIfExactMatches_NewVim_test():
def GetCompletionsUserMayHaveCompleted_ReturnMatchIfExactMatches_NewVim_test():
info = [ "NS","Test", "Abbr", "Menu", "Info", "Kind" ]
completions = [ _BuildCompletion( *info ) ]
ycm_state = _SetupForCsharpCompletionDone( completions )
vimsupport.VimVersionAtLeast = MagicMock( return_value = True )
vimsupport.GetVariableValue = GetVariableValue_CompleteItemIs( *info[ 1 : ] )
eq_( completions, ycm_state.GetCompletedCompletions() )
eq_( completions, ycm_state.GetCompletionsUserMayHaveCompleted() )
def GetCompletedCompletions_ReturnMatchIfExactMatchesEvenIfPartial_NewVim_test():
def GetCompletionsUserMayHaveCompleted_ReturnMatchIfExactMatchesEvenIfPartial_NewVim_test():
info = [ "NS", "Test", "Abbr", "Menu", "Info", "Kind" ]
completions = [ _BuildCompletion( *info ),
_BuildCompletion( insertion_text = "TestTest" ) ]
@ -280,10 +280,10 @@ def GetCompletedCompletions_ReturnMatchIfExactMatchesEvenIfPartial_NewVim_test()
vimsupport.VimVersionAtLeast = MagicMock( return_value = True )
vimsupport.GetVariableValue = GetVariableValue_CompleteItemIs( *info[ 1 : ] )
eq_( [ completions[ 0 ] ], ycm_state.GetCompletedCompletions() )
eq_( [ completions[ 0 ] ], ycm_state.GetCompletionsUserMayHaveCompleted() )
def GetCompletedCompletions_DontReturnMatchIfNontExactMatchesAndPartial_NewVim_test():
def GetCompletionsUserMayHaveCompleted_DontReturnMatchIfNontExactMatchesAndPartial_NewVim_test():
info = [ "NS", "Test", "Abbr", "Menu", "Info", "Kind" ]
completions = [ _BuildCompletion( insertion_text = info[ 0 ] ),
_BuildCompletion( insertion_text = "TestTest" ) ]
@ -291,31 +291,31 @@ def GetCompletedCompletions_DontReturnMatchIfNontExactMatchesAndPartial_NewVim_t
vimsupport.VimVersionAtLeast = MagicMock( return_value = True )
vimsupport.GetVariableValue = GetVariableValue_CompleteItemIs( *info[ 1 : ] )
eq_( [], ycm_state.GetCompletedCompletions() )
eq_( [], ycm_state.GetCompletionsUserMayHaveCompleted() )
def GetCompletedCompletions_ReturnMatchIfMatches_NewVim_test():
def GetCompletionsUserMayHaveCompleted_ReturnMatchIfMatches_NewVim_test():
completions = [ _BuildCompletion( None ) ]
ycm_state = _SetupForCsharpCompletionDone( completions )
vimsupport.VimVersionAtLeast = MagicMock( return_value = True )
vimsupport.GetVariableValue = GetVariableValue_CompleteItemIs( "Test" )
eq_( completions, ycm_state.GetCompletedCompletions() )
eq_( completions, ycm_state.GetCompletionsUserMayHaveCompleted() )
def GetCompletedCompletions_ReturnMatchIfMatches_OldVim_test():
def GetCompletionsUserMayHaveCompleted_ReturnMatchIfMatches_OldVim_test():
completions = [ _BuildCompletion( None ) ]
ycm_state = _SetupForCsharpCompletionDone( completions )
vimsupport.VimVersionAtLeast = MagicMock( return_value = False )
vimsupport.TextBeforeCursor = MagicMock( return_value = " Test" )
eq_( completions, ycm_state.GetCompletedCompletions() )
eq_( completions, ycm_state.GetCompletionsUserMayHaveCompleted() )
def PostCompleteCsharp_EmptyDoesntInsertNamespace_test():
ycm_state = _SetupForCsharpCompletionDone( [] )
ycm_state.OnCompleteDone_Csharp()
ycm_state._OnCompleteDone_Csharp()
assert not vimsupport.InsertNamespace.called
@ -324,7 +324,7 @@ def PostCompleteCsharp_ExistingWithoutNamespaceDoesntInsertNamespace_test():
completions = [ _BuildCompletion( None ) ]
ycm_state = _SetupForCsharpCompletionDone( completions )
ycm_state.OnCompleteDone_Csharp()
ycm_state._OnCompleteDone_Csharp()
assert not vimsupport.InsertNamespace.called
@ -334,7 +334,7 @@ def PostCompleteCsharp_ValueDoesInsertNamespace_test():
completions = [ _BuildCompletion( namespace ) ]
ycm_state = _SetupForCsharpCompletionDone( completions )
ycm_state.OnCompleteDone_Csharp()
ycm_state._OnCompleteDone_Csharp()
vimsupport.InsertNamespace.assert_called_once_with( namespace )
@ -348,7 +348,7 @@ def PostCompleteCsharp_InsertSecondNamespaceIfSelected_test():
ycm_state = _SetupForCsharpCompletionDone( completions )
vimsupport.PresentDialog = MagicMock( return_value = 1 )
ycm_state.OnCompleteDone_Csharp()
ycm_state._OnCompleteDone_Csharp()
vimsupport.InsertNamespace.assert_called_once_with( namespace2 )
@ -376,6 +376,7 @@ def _BuildCompletion( namespace = None, insertion_text = 'Test',
'detailed_info': detailed_info,
}
def GetVariableValue_CompleteItemIs( word, abbr = None, menu = None,
info = None, kind = None ):
def Result( variable ):

View File

@ -99,7 +99,7 @@ class YouCompleteMe( object ):
self._SetupServer()
self._ycmd_keepalive.Start()
self._complete_done_hooks = {
'cs': lambda( self ): self.OnCompleteDone_Csharp()
'cs': lambda( self ): self._OnCompleteDone_Csharp()
}
def _SetupServer( self ):
@ -310,89 +310,121 @@ class YouCompleteMe( object ):
yield value
def GetCompletedCompletions( self ):
def GetCompletionsUserMayHaveCompleted( self ):
latest_completion_request = self.GetCurrentCompletionRequest()
if not latest_completion_request or not latest_completion_request.Done():
return []
completions = latest_completion_request.RawResponse()
result = self.FilterToCompletedCompletions( completions,
full_match_only = True )
result = self._FilterToMatchingCompletions( completions, True )
result = list( result )
if result:
return result
if self.HasCompletionsThatCouldBeCompletedWithMoreText( completions ):
if self._HasCompletionsThatCouldBeCompletedWithMoreText( completions ):
# Since the way that YCM works leads to CompleteDone called on every
# character, return blank if the completion might not be done. This won't
# match if the completion is ended with typing a non-keyword character.
return []
result = self.FilterToCompletedCompletions( completions,
full_match_only = False )
result = self._FilterToMatchingCompletions( completions, False )
return list( result )
def FilterToCompletedCompletions( self, completions, full_match_only ):
def _FilterToMatchingCompletions( self, completions, full_match_only ):
self._PatchBasedOnVimVersion()
return self._FilterToMatchingCompletions( completions, full_match_only)
def _HasCompletionsThatCouldBeCompletedWithMoreText( self, completions ):
self._PatchBasedOnVimVersion()
return self._HasCompletionsThatCouldBeCompletedWithMoreText( completions )
def _PatchBasedOnVimVersion( self ):
if vimsupport.VimVersionAtLeast( "7.4.774" ):
completed = vimsupport.GetVariableValue( 'v:completed_item' )
for completion in completions:
item = ConvertCompletionDataToVimData( completion )
match_keys = ( [ "word", "abbr", "menu", "info" ] if full_match_only
else [ 'word' ] )
matcher = lambda key: completed.get( key, "" ) == item.get( key, "" )
if all( [ matcher( i ) for i in match_keys ] ):
yield completion
self._HasCompletionsThatCouldBeCompletedWithMoreText = \
self._HasCompletionsThatCouldBeCompletedWithMoreText_NewerVim
self._FilterToMatchingCompletions = \
self._FilterToMatchingCompletions_NewerVim
else:
if full_match_only:
return
# No support for multiple line completions
text = vimsupport.TextBeforeCursor()
for completion in completions:
word = completion[ "insertion_text" ]
# Trim complete-ending character if needed
text = re.sub( r"[^a-zA-Z0-9_]$", "", text )
buffer_text = text[ -1 * len( word ) : ]
if buffer_text == word:
yield completion
self._FilterToMatchingCompletions = \
self._FilterToMatchingCompletions_OlderVim
self._HasCompletionsThatCouldBeCompletedWithMoreText = \
self._HasCompletionsThatCouldBeCompletedWithMoreText_OlderVim
def HasCompletionsThatCouldBeCompletedWithMoreText( self, completions ):
if vimsupport.VimVersionAtLeast( "7.4.774" ):
completed_item = vimsupport.GetVariableValue( 'v:completed_item' )
completed_word = completed_item[ 'word' ]
if not completed_word:
return False
def _FilterToMatchingCompletions_NewerVim( self, completions,
full_match_only ):
""" Filter to completions matching the item Vim said was completed """
completed = vimsupport.GetVariableValue( 'v:completed_item' )
for completion in completions:
item = ConvertCompletionDataToVimData( completion )
match_keys = ( [ "word", "abbr", "menu", "info" ] if full_match_only
else [ 'word' ] )
matcher = lambda key: completed.get( key, "" ) == item.get( key, "" )
if all( [ matcher( i ) for i in match_keys ] ):
yield completion
# Sometime CompleteDone is called after the next character is inserted
# If so, use inserted character to filter possible completions further
text = vimsupport.TextBeforeCursor()
reject_exact_match = True
if text and text[ -1 ] != completed_word[ -1 ]:
reject_exact_match = False
completed_word += text[ -1 ]
for completion in completions:
word = ConvertCompletionDataToVimData( completion )[ 'word' ]
if reject_exact_match and word == completed_word:
continue
if word.startswith( completed_word ):
return True
else:
text = vimsupport.TextBeforeCursor() # No support for multiple line completions
for completion in completions:
word = ConvertCompletionDataToVimData( completion )[ 'word' ]
for i in range( 1, len( word ) - 1 ): # Excluding full word
if text[ -1 * i : ] == word[ : i ]:
return True
def _FilterToMatchingCompletions_OlderVim( self, completions,
full_match_only ):
""" Filter to completions matching the buffer text """
if full_match_only:
return # Only supported in 7.4.774+
# No support for multiple line completions
text = vimsupport.TextBeforeCursor()
for completion in completions:
word = completion[ "insertion_text" ]
# Trim complete-ending character if needed
text = re.sub( r"[^a-zA-Z0-9_]$", "", text )
buffer_text = text[ -1 * len( word ) : ]
if buffer_text == word:
yield completion
def _HasCompletionsThatCouldBeCompletedWithMoreText_NewerVim( self,
completions ):
completed_item = vimsupport.GetVariableValue( 'v:completed_item' )
completed_word = completed_item[ 'word' ]
if not completed_word:
return False
# Sometime CompleteDone is called after the next character is inserted
# If so, use inserted character to filter possible completions further
text = vimsupport.TextBeforeCursor()
reject_exact_match = True
if text and text[ -1 ] != completed_word[ -1 ]:
reject_exact_match = False
completed_word += text[ -1 ]
for completion in completions:
word = ConvertCompletionDataToVimData( completion )[ 'word' ]
if reject_exact_match and word == completed_word:
continue
if word.startswith( completed_word ):
return True
return False
def OnCompleteDone_Csharp( self ):
completions = self.GetCompletedCompletions()
namespaces = [ self.GetRequiredNamespaceImport( c )
def _HasCompletionsThatCouldBeCompletedWithMoreText_OlderVim( self,
completions ):
# No support for multiple line completions
text = vimsupport.TextBeforeCursor()
for completion in completions:
word = ConvertCompletionDataToVimData( completion )[ 'word' ]
for i in range( 1, len( word ) - 1 ): # Excluding full word
if text[ -1 * i : ] == word[ : i ]:
return True
return False
def _OnCompleteDone_Csharp( self ):
completions = self.GetCompletionsUserMayHaveCompleted()
namespaces = [ self._GetRequiredNamespaceImport( c )
for c in completions ]
namespaces = [ n for n in namespaces if n ]
if not namespaces:
@ -411,7 +443,7 @@ class YouCompleteMe( object ):
vimsupport.InsertNamespace( namespace )
def GetRequiredNamespaceImport( self, completion ):
def _GetRequiredNamespaceImport( self, completion ):
if ( "extra_data" not in completion
or "required_namespace_import" not in completion[ "extra_data" ] ):
return None
@ -542,5 +574,3 @@ def _AddUltiSnipsDataIfNeeded( extra_data ):
extra_data[ 'ultisnips_snippets' ] = [ { 'trigger': x.trigger,
'description': x.description
} for x in rawsnips ]