diff --git a/python/ycm/client/command_request.py b/python/ycm/client/command_request.py index 565bf80c2c..c09ae4a8d2 100644 --- a/python/ycm/client/command_request.py +++ b/python/ycm/client/command_request.py @@ -15,6 +15,8 @@ # You should have received a copy of the GNU General Public License # along with YouCompleteMe. If not, see . +import re + from ycm.client.base_request import BaseRequest, BuildRequestData from ycm import vimsupport @@ -165,10 +167,22 @@ def _HandleFixitResponse( self ): ( len( fixits ) == 1 and self._command == 'FixIt' and fixits[ 0 ].get( 'kind' ) != 'quickfix' ) ): - fixit_index = vimsupport.SelectFromList( - "FixIt suggestion(s) available at this location. " - "Which one would you like to apply?", - [ fixit[ 'text' ] for fixit in fixits ] ) + # If the user provided another argument, use it as a pattern to + # automatically select the fixit to apply. + if len( self._arguments ) == 2: + pat = self._arguments[ 1 ] + fixit_index = _FindFirstIndex( + lambda fixit: re.search( pat, fixit[ 'text' ] ), + fixits ) + if fixit_index is None: + vimsupport.PostVimMessage( + f'No fixits found for current line matching {pat}' ) + return + else: + fixit_index = vimsupport.SelectFromList( + "FixIt suggestion(s) available at this location. " + "Which one would you like to apply?", + [ fixit[ 'text' ] for fixit in fixits ] ) chosen_fixit = fixits[ fixit_index ] if chosen_fixit[ 'resolve' ]: self._request_data.update( { 'fixit': chosen_fixit } ) @@ -226,3 +240,9 @@ def GetCommandResponse( arguments, extra_data = None ): silent = True ) # Block here to get the response return request.StringResponse() + + +def _FindFirstIndex( matcher, items ): + return next( + ( i for ( i, item ) in enumerate( items ) if matcher( item ) ), + None ) diff --git a/python/ycm/tests/client/command_request_test.py b/python/ycm/tests/client/command_request_test.py index 7af6e4852e..07e1a3cf77 100644 --- a/python/ycm/tests/client/command_request_test.py +++ b/python/ycm/tests/client/command_request_test.py @@ -254,6 +254,37 @@ def FixItTest( command, response, chunks, selection, silent ): FixItTest( command, response, chunks, selection, silent ) + def test_FixIt_WithPattern_Response( self ): + # Ensures we recognise and handle fixit responses with some dummy chunk data + def FixItTest( pattern, response, chunks, silent ): + with patch( 'ycm.vimsupport.ReplaceChunks' ) as replace_chunks: + with patch( 'ycm.vimsupport.PostVimMessage' ) as post_vim_message: + request = CommandRequest( [ 'FixIt', pattern ] ) + request._response = response + request.RunPostCommandActionsIfNeeded( 'leftabove' ) + + if chunks: + replace_chunks.assert_called_with( chunks, silent = silent ) + post_vim_message.assert_not_called() + else: + replace_chunks.assert_not_called() + post_vim_message.assert_called() + + for pattern, response, chunks, silent in [ + [ 'irsr?', + MULTI_FIXIT, MULTI_FIXIT_FIRST_CHUNKS, False ], + [ 'e.o', + MULTI_FIXIT, MULTI_FIXIT_SECOND_CHUNKS, False ], + [ 'none', + MULTI_FIXIT, None, False ], + ]: + with self.subTest( pattern = pattern, + response = response, + chunks = chunks, + silent = silent ): + FixItTest( pattern, response, chunks, silent ) + + def test_Message_Response( self ): # Ensures we correctly recognise and handle responses with a message to show # to the user