Auto merge of #2970 - micbou:duplicate-fixits, r=puremourning
[READY] Fix applying fixit twice after completion Fixes the issue mentioned in PR https://github.com/Valloric/YouCompleteMe/pull/2963 for Vim 8.0.1493 and later. I don't think it's worth the trouble to fix the issue for older versions. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/valloric/youcompleteme/2970) <!-- Reviewable:end -->
This commit is contained in:
commit
45502e5108
@ -1,4 +1,4 @@
|
|||||||
# Copyright (C) 2013 Google Inc.
|
# Copyright (C) 2013-2018 YouCompleteMe contributors
|
||||||
#
|
#
|
||||||
# This file is part of YouCompleteMe.
|
# This file is part of YouCompleteMe.
|
||||||
#
|
#
|
||||||
@ -93,35 +93,22 @@ class CompletionRequest( BaseRequest ):
|
|||||||
|
|
||||||
def _GetCompletionsUserMayHaveCompleted( self ):
|
def _GetCompletionsUserMayHaveCompleted( self ):
|
||||||
completed_item = vimsupport.GetVariableValue( 'v:completed_item' )
|
completed_item = vimsupport.GetVariableValue( 'v:completed_item' )
|
||||||
completions = self.RawResponse()[ 'completions' ]
|
|
||||||
|
|
||||||
if 'user_data' in completed_item and completed_item[ 'user_data' ]:
|
# If Vim supports user_data (8.0.1493 or later), we actually know the
|
||||||
# Vim supports user_data (8.0.1493) or later, so we actually know the
|
|
||||||
# _exact_ element that was selected, having put its index in the
|
# _exact_ element that was selected, having put its index in the
|
||||||
# user_data field.
|
# user_data field. Otherwise, we have to guess by matching the values in the
|
||||||
|
# completed item and the list of completions. Sometimes this returns
|
||||||
|
# multiple possibilities, which is essentially unresolvable.
|
||||||
|
if 'user_data' not in completed_item:
|
||||||
|
completions = self.RawResponse()[ 'completions' ]
|
||||||
|
return _FilterToMatchingCompletions( completed_item, completions )
|
||||||
|
|
||||||
|
if completed_item[ 'user_data' ]:
|
||||||
|
completions = self.RawResponse()[ 'completions' ]
|
||||||
return [ completions[ int( completed_item[ 'user_data' ] ) ] ]
|
return [ completions[ int( completed_item[ 'user_data' ] ) ] ]
|
||||||
|
|
||||||
# Otherwise, we have to guess by matching the values in the completed item
|
|
||||||
# and the list of completions. Sometimes this returns multiple
|
|
||||||
# possibilities, which is essentially unresolvable.
|
|
||||||
|
|
||||||
result = _FilterToMatchingCompletions( completed_item, completions, True )
|
|
||||||
result = list( result )
|
|
||||||
|
|
||||||
if result:
|
|
||||||
return result
|
|
||||||
|
|
||||||
if _HasCompletionsThatCouldBeCompletedWithMoreText( completed_item,
|
|
||||||
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 []
|
return []
|
||||||
|
|
||||||
result = _FilterToMatchingCompletions( completed_item, completions, False )
|
|
||||||
|
|
||||||
return list( result )
|
|
||||||
|
|
||||||
|
|
||||||
def _OnCompleteDone_Csharp( self ):
|
def _OnCompleteDone_Csharp( self ):
|
||||||
completions = self._GetCompletionsUserMayHaveCompleted()
|
completions = self._GetCompletionsUserMayHaveCompleted()
|
||||||
@ -178,13 +165,10 @@ def _GetFixItCompletion( completion ):
|
|||||||
return completion[ 'extra_data' ][ 'fixits' ]
|
return completion[ 'extra_data' ][ 'fixits' ]
|
||||||
|
|
||||||
|
|
||||||
def _FilterToMatchingCompletions( completed_item,
|
def _FilterToMatchingCompletions( completed_item, completions ):
|
||||||
completions,
|
|
||||||
full_match_only ):
|
|
||||||
"""Filter to completions matching the item Vim said was completed"""
|
"""Filter to completions matching the item Vim said was completed"""
|
||||||
match_keys = ( [ 'word', 'abbr', 'menu', 'info' ] if full_match_only
|
match_keys = [ 'word', 'abbr', 'menu', 'info' ]
|
||||||
else [ 'word' ] )
|
matched_completions = []
|
||||||
|
|
||||||
for index, completion in enumerate( completions ):
|
for index, completion in enumerate( completions ):
|
||||||
item = _ConvertCompletionDataToVimData( index, completion )
|
item = _ConvertCompletionDataToVimData( index, completion )
|
||||||
|
|
||||||
@ -193,34 +177,8 @@ def _FilterToMatchingCompletions( completed_item,
|
|||||||
ToUnicode( item.get( key, "" ) ) )
|
ToUnicode( item.get( key, "" ) ) )
|
||||||
|
|
||||||
if all( [ matcher( i ) for i in match_keys ] ):
|
if all( [ matcher( i ) for i in match_keys ] ):
|
||||||
yield completion
|
matched_completions.append( completion )
|
||||||
|
return matched_completions
|
||||||
|
|
||||||
def _HasCompletionsThatCouldBeCompletedWithMoreText( completed_item,
|
|
||||||
completions ):
|
|
||||||
if not completed_item:
|
|
||||||
return False
|
|
||||||
|
|
||||||
completed_word = ToUnicode( completed_item[ 'word' ] )
|
|
||||||
if not completed_word:
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Sometimes 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 index, completion in enumerate( completions ):
|
|
||||||
word = ToUnicode(
|
|
||||||
_ConvertCompletionDataToVimData( index, completion )[ 'word' ] )
|
|
||||||
if reject_exact_match and word == completed_word:
|
|
||||||
continue
|
|
||||||
if word.startswith( completed_word ):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def _ConvertCompletionDataToVimData( completion_identifier, completion_data ):
|
def _ConvertCompletionDataToVimData( completion_identifier, completion_data ):
|
||||||
|
@ -33,11 +33,9 @@ from nose.tools import eq_, ok_
|
|||||||
|
|
||||||
from ycm import vimsupport
|
from ycm import vimsupport
|
||||||
from ycmd.utils import ToBytes
|
from ycmd.utils import ToBytes
|
||||||
from ycm.client.completion_request import (
|
from ycm.client.completion_request import ( CompletionRequest,
|
||||||
CompletionRequest,
|
|
||||||
_FilterToMatchingCompletions,
|
_FilterToMatchingCompletions,
|
||||||
_GetRequiredNamespaceImport,
|
_GetRequiredNamespaceImport )
|
||||||
_HasCompletionsThatCouldBeCompletedWithMoreText )
|
|
||||||
|
|
||||||
|
|
||||||
def CompleteItemIs( word, abbr = None, menu = None,
|
def CompleteItemIs( word, abbr = None, menu = None,
|
||||||
@ -185,88 +183,36 @@ def OnCompleteDone_NoActionIfNotDone_test( *args ):
|
|||||||
|
|
||||||
def FilterToCompletedCompletions_MatchIsReturned_test():
|
def FilterToCompletedCompletions_MatchIsReturned_test():
|
||||||
completions = [ BuildCompletion( insertion_text = 'Test' ) ]
|
completions = [ BuildCompletion( insertion_text = 'Test' ) ]
|
||||||
result = _FilterToMatchingCompletions( CompleteItemIs( 'Test' ),
|
result = _FilterToMatchingCompletions( CompleteItemIs( 'Test' ), completions )
|
||||||
completions,
|
|
||||||
False )
|
|
||||||
eq_( list( result ), completions )
|
eq_( list( result ), completions )
|
||||||
|
|
||||||
|
|
||||||
def FilterToCompletedCompletions_ShortTextDoesntRaise_test():
|
def FilterToCompletedCompletions_ShortTextDoesntRaise_test():
|
||||||
completions = [ BuildCompletion( insertion_text = 'AAA' ) ]
|
completions = [ BuildCompletion( insertion_text = 'AAA' ) ]
|
||||||
result = _FilterToMatchingCompletions( CompleteItemIs( 'A' ),
|
result = _FilterToMatchingCompletions( CompleteItemIs( 'A' ), completions )
|
||||||
completions,
|
|
||||||
False )
|
|
||||||
eq_( list( result ), [] )
|
eq_( list( result ), [] )
|
||||||
|
|
||||||
|
|
||||||
def FilterToCompletedCompletions_ExactMatchIsReturned_test():
|
def FilterToCompletedCompletions_ExactMatchIsReturned_test():
|
||||||
completions = [ BuildCompletion( insertion_text = 'Test' ) ]
|
completions = [ BuildCompletion( insertion_text = 'Test' ) ]
|
||||||
result = _FilterToMatchingCompletions( CompleteItemIs( 'Test' ),
|
result = _FilterToMatchingCompletions( CompleteItemIs( 'Test' ), completions )
|
||||||
completions,
|
|
||||||
False )
|
|
||||||
eq_( list( result ), completions )
|
eq_( list( result ), completions )
|
||||||
|
|
||||||
|
|
||||||
def FilterToCompletedCompletions_NonMatchIsntReturned_test():
|
def FilterToCompletedCompletions_NonMatchIsntReturned_test():
|
||||||
completions = [ BuildCompletion( insertion_text = 'A' ) ]
|
completions = [ BuildCompletion( insertion_text = 'A' ) ]
|
||||||
result = _FilterToMatchingCompletions( CompleteItemIs( ' Quote' ),
|
result = _FilterToMatchingCompletions( CompleteItemIs( ' Quote' ),
|
||||||
completions,
|
completions )
|
||||||
False )
|
|
||||||
eq_( list( result ), [] )
|
eq_( list( result ), [] )
|
||||||
|
|
||||||
|
|
||||||
def FilterToCompletedCompletions_Unicode_test():
|
def FilterToCompletedCompletions_Unicode_test():
|
||||||
completions = [ BuildCompletion( insertion_text = '†es†' ) ]
|
completions = [ BuildCompletion( insertion_text = '†es†' ) ]
|
||||||
result = _FilterToMatchingCompletions( CompleteItemIs( '†es†' ),
|
result = _FilterToMatchingCompletions( CompleteItemIs( '†es†' ),
|
||||||
completions,
|
completions )
|
||||||
False )
|
|
||||||
eq_( list( result ), completions )
|
eq_( list( result ), completions )
|
||||||
|
|
||||||
|
|
||||||
@patch( 'ycm.vimsupport.TextBeforeCursor', return_value = ' Quote' )
|
|
||||||
def HasCompletionsThatCouldBeCompletedWithMoreText_MatchIsReturned_test(
|
|
||||||
*args ):
|
|
||||||
completions = [ BuildCompletion( insertion_text = 'Test' ) ]
|
|
||||||
ok_( _HasCompletionsThatCouldBeCompletedWithMoreText( CompleteItemIs( 'Te' ),
|
|
||||||
completions ) )
|
|
||||||
|
|
||||||
|
|
||||||
@patch( 'ycm.vimsupport.TextBeforeCursor', return_value = ' Quote' )
|
|
||||||
def HasCompletionsThatCouldBeCompletedWithMoreText_ShortTextDoesntRaise_test(
|
|
||||||
*args ):
|
|
||||||
completions = [ BuildCompletion( insertion_text = 'AAA' ) ]
|
|
||||||
ok_( not _HasCompletionsThatCouldBeCompletedWithMoreText(
|
|
||||||
CompleteItemIs( 'X' ),
|
|
||||||
completions ) )
|
|
||||||
|
|
||||||
|
|
||||||
@patch( 'ycm.vimsupport.TextBeforeCursor', return_value = ' Quote' )
|
|
||||||
def HasCompletionsThatCouldBeCompletedWithMoreText_ExactMatchIsntReturned_test(
|
|
||||||
*args ):
|
|
||||||
completions = [ BuildCompletion( insertion_text = 'Test' ) ]
|
|
||||||
ok_( not _HasCompletionsThatCouldBeCompletedWithMoreText(
|
|
||||||
CompleteItemIs( 'Test' ),
|
|
||||||
completions ) )
|
|
||||||
|
|
||||||
|
|
||||||
@patch( 'ycm.vimsupport.TextBeforeCursor', return_value = ' Quote' )
|
|
||||||
def HasCompletionsThatCouldBeCompletedWithMoreText_NonMatchIsntReturned_test(
|
|
||||||
*args ):
|
|
||||||
completions = [ BuildCompletion( insertion_text = "A" ) ]
|
|
||||||
ok_( not _HasCompletionsThatCouldBeCompletedWithMoreText(
|
|
||||||
CompleteItemIs( ' Quote' ),
|
|
||||||
completions ) )
|
|
||||||
|
|
||||||
|
|
||||||
@patch( 'ycm.vimsupport.TextBeforeCursor', return_value = 'Uniç' )
|
|
||||||
def HasCompletionsThatCouldBeCompletedWithMoreText_Unicode_test(
|
|
||||||
*args ):
|
|
||||||
completions = [ BuildCompletion( insertion_text = 'Uniçø∂¢' ) ]
|
|
||||||
ok_( _HasCompletionsThatCouldBeCompletedWithMoreText(
|
|
||||||
CompleteItemIs( 'Uniç' ),
|
|
||||||
completions ) )
|
|
||||||
|
|
||||||
|
|
||||||
def GetRequiredNamespaceImport_ReturnNoneForNoExtraData_test():
|
def GetRequiredNamespaceImport_ReturnNoneForNoExtraData_test():
|
||||||
eq_( _GetRequiredNamespaceImport( {} ), None )
|
eq_( _GetRequiredNamespaceImport( {} ), None )
|
||||||
|
|
||||||
@ -351,6 +297,19 @@ def GetCompletionsUserMayHaveCompleted_UseUserData1_test( *args ):
|
|||||||
[ BuildCompletionNamespace( 'namespace2' ) ] )
|
[ BuildCompletionNamespace( 'namespace2' ) ] )
|
||||||
|
|
||||||
|
|
||||||
|
@patch( 'ycm.vimsupport.GetVariableValue',
|
||||||
|
GetVariableValue_CompleteItemIs( 'Test', user_data='' ) )
|
||||||
|
def GetCompletionsUserMayHaveCompleted_EmptyUserData_test( *args ):
|
||||||
|
# Identical completions but none is selected.
|
||||||
|
completions = [
|
||||||
|
BuildCompletionNamespace( 'namespace1' ),
|
||||||
|
BuildCompletionNamespace( 'namespace2' )
|
||||||
|
]
|
||||||
|
|
||||||
|
with _SetupForCsharpCompletionDone( completions ) as request:
|
||||||
|
eq_( request._GetCompletionsUserMayHaveCompleted(), [] )
|
||||||
|
|
||||||
|
|
||||||
@patch( 'ycm.vimsupport.GetVariableValue',
|
@patch( 'ycm.vimsupport.GetVariableValue',
|
||||||
GetVariableValue_CompleteItemIs( 'Test' ) )
|
GetVariableValue_CompleteItemIs( 'Test' ) )
|
||||||
def PostCompleteCsharp_EmptyDoesntInsertNamespace_test( *args ):
|
def PostCompleteCsharp_EmptyDoesntInsertNamespace_test( *args ):
|
||||||
|
Loading…
Reference in New Issue
Block a user