def LanguageServerCompleter_GetCompletions_CompleteOnStartColumn_test( app ): completer = MockCompleter() completer._resolve_completion_items = False complete_response = { 'result': { 'items': [ { 'label': 'aa' }, { 'label': 'ac' }, { 'label': 'ab' } ], 'isIncomplete': False } } with patch.object( completer, '_is_completion_provider', True ): request_data = RequestWrap( BuildRequest( column_num = 2, contents = 'a', force_semantic = True ) ) with patch.object( completer.GetConnection(), 'GetResponse', return_value = complete_response ) as response: assert_that( completer.ComputeCandidates( request_data ), contains_exactly( has_entry( 'insertion_text', 'aa' ), has_entry( 'insertion_text', 'ab' ), has_entry( 'insertion_text', 'ac' ) ) ) # Nothing cached yet. assert_that( response.call_count, equal_to( 1 ) ) request_data = RequestWrap( BuildRequest( column_num = 3, contents = 'ab', force_semantic = True ) ) with patch.object( completer.GetConnection(), 'GetResponse', return_value = complete_response ) as response: assert_that( completer.ComputeCandidates( request_data ), contains_exactly( has_entry( 'insertion_text', 'ab' ) ) ) # Since the server returned a complete list of completions on the starting # column, no request should be sent to the server and the cache should be # used instead. assert_that( response.call_count, equal_to( 0 ) )
def LanguageServerCompleter_GetCodeActions_CursorOnEmptyLine_test( app ): completer = MockCompleter() request_data = RequestWrap( BuildRequest( line_num = 1, column_num = 1, contents = '' ) ) fixit_response = { 'result': [] } with patch.object( completer, '_ServerIsInitialized', return_value = True ): with patch.object( completer.GetConnection(), 'GetResponse', side_effect = [ fixit_response ] ): with patch( 'ycmd.completers.language_server.language_server_protocol.' 'CodeAction' ) as code_action: assert_that( completer.GetCodeActions( request_data, [] ), has_entry( 'fixits', empty() ) ) assert_that( # Range passed to lsp.CodeAction. # LSP requires to use the start of the next line as the end position # for a range that ends with a newline. code_action.call_args[ 0 ][ 2 ], has_entries( { 'start': has_entries( { 'line': 0, 'character': 0 } ), 'end': has_entries( { 'line': 1, 'character': 0 } ) } ) )
def LanguageServerCompleter_OnFileSave_BeforeServerReady_test( app ): completer = MockCompleter() request_data = RequestWrap( BuildRequest() ) with patch.object( completer, 'ServerIsReady', return_value = False ): with patch.object( completer.GetConnection(), 'SendNotification' ) as send_notification: completer.OnFileSave( request_data ) send_notification.assert_not_called()
def LanguageServerCompleter_Diagnostics_PercentEncodeCannonical_test( app ): completer = MockCompleter() filepath = os.path.realpath( '/foo?' ) uri = lsp.FilePathToUri( filepath ) assert_that( uri, ends_with( '%3F' ) ) request_data = RequestWrap( BuildRequest( line_num = 1, column_num = 1, filepath = filepath, contents = '' ) ) notification = { 'jsonrpc': '2.0', 'method': 'textDocument/publishDiagnostics', 'params': { 'uri': uri.replace( '%3F', '%3f' ), 'diagnostics': [ { 'range': { 'start': { 'line': 3, 'character': 10 }, 'end': { 'line': 3, 'character': 11 } }, 'severity': 1, 'message': 'First error' } ] } } completer.GetConnection()._notifications.put( notification ) completer.HandleNotificationInPollThread( notification ) with patch.object( completer, '_ServerIsInitialized', return_value = True ): completer.OnFileReadyToParse( request_data ) # Simulate receipt of response and initialization complete initialize_response = { 'result': { 'capabilities': {} } } completer._HandleInitializeInPollThread( initialize_response ) diagnostics = contains_exactly( has_entries( { 'kind': equal_to( 'ERROR' ), 'location': LocationMatcher( filepath, 4, 11 ), 'location_extent': RangeMatcher( filepath, ( 4, 11 ), ( 4, 12 ) ), 'ranges': contains_exactly( RangeMatcher( filepath, ( 4, 11 ), ( 4, 12 ) ) ), 'text': equal_to( 'First error' ), 'fixit_available': False } ) ) assert_that( completer.OnFileReadyToParse( request_data ), diagnostics ) assert_that( completer.PollForMessages( request_data ), contains_exactly( has_entries( { 'diagnostics': diagnostics, 'filepath': filepath } ) ) )
def LanguageServerCompleter_GetHoverResponse_test( app ): completer = MockCompleter() request_data = RequestWrap( BuildRequest( line_num = 1, column_num = 1, contents = '' ) ) with patch.object( completer, '_ServerIsInitialized', return_value = True ): with patch.object( completer.GetConnection(), 'GetResponse', side_effect = [ { 'result': None } ] ): assert_that( calling( completer.GetHoverResponse ).with_args( request_data ), raises( NoHoverInfoException, NO_HOVER_INFORMATION ) ) with patch.object( completer.GetConnection(), 'GetResponse', side_effect = [ { 'result': { 'contents': 'test' } } ] ): assert_that( completer.GetHoverResponse( request_data ), equal_to( 'test' ) )
def LanguageServerCompleter_OnFileReadyToParse_InvalidURI_test( app ): completer = MockCompleter() filepath = os.path.realpath( '/foo?' ) uri = lsp.FilePathToUri( filepath ) request_data = RequestWrap( BuildRequest( line_num = 1, column_num = 1, filepath = filepath, contents = '' ) ) notification = { 'jsonrpc': '2.0', 'method': 'textDocument/publishDiagnostics', 'params': { 'uri': uri, 'diagnostics': [ { 'range': { 'start': { 'line': 3, 'character': 10 }, 'end': { 'line': 3, 'character': 11 } }, 'severity': 1, 'message': 'First error' } ] } } completer.GetConnection()._notifications.put( notification ) completer.HandleNotificationInPollThread( notification ) with patch.object( completer, '_ServerIsInitialized', return_value = True ): completer.OnFileReadyToParse( request_data ) # Simulate receipt of response and initialization complete initialize_response = { 'result': { 'capabilities': {} } } completer._HandleInitializeInPollThread( initialize_response ) diagnostics = contains_exactly( has_entries( { 'kind': equal_to( 'ERROR' ), 'location': LocationMatcher( '', 4, 11 ), 'location_extent': RangeMatcher( '', ( 4, 11 ), ( 4, 12 ) ), 'ranges': contains_exactly( RangeMatcher( '', ( 4, 11 ), ( 4, 12 ) ) ), 'text': equal_to( 'First error' ), 'fixit_available': False } ) ) with patch( 'ycmd.completers.language_server.language_server_protocol.' 'UriToFilePath', side_effect = lsp.InvalidUriException ) as \ uri_to_filepath: assert_that( completer.OnFileReadyToParse( request_data ), diagnostics ) uri_to_filepath.assert_called()
def LanguageServerCompleter_Initialise_Shutdown_test( app ): completer = MockCompleter() request_data = RequestWrap( BuildRequest() ) with patch.object( completer.GetConnection(), 'ReadData', side_effect = lsc.LanguageServerConnectionStopped ): assert_that( completer.ServerIsReady(), equal_to( False ) ) completer.OnFileReadyToParse( request_data ) with patch.object( completer, '_HandleInitializeInPollThread' ) as handler: completer.GetConnection().run() handler.assert_not_called() assert_that( completer._initialize_event.is_set(), equal_to( False ) ) assert_that( completer.ServerIsReady(), equal_to( False ) ) with patch.object( completer, 'ServerIsHealthy', return_value = False ): assert_that( completer.ServerIsReady(), equal_to( False ) )
def LanguageServerCompleter_RejectWorkspaceConfigurationRequest_test( app ): completer = MockCompleter() notification = { 'jsonrpc': '2.0', 'method': 'workspace/configuration', 'id': 1234, 'params': { 'items': [ { 'section': 'whatever' } ] } } with patch( 'ycmd.completers.language_server.' 'language_server_protocol.Reject' ) as reject: completer.GetConnection()._DispatchMessage( notification ) reject.assert_called_with( notification, lsp.Errors.MethodNotFound )
def Test( responses, command, exception, throws, *args ): with patch.object( completer.GetConnection(), 'GetResponse', side_effect = responses ): if throws: assert_that( calling( completer.OnUserCommand ).with_args( [ command ], request_data ), raises( exception ) ) else: result = completer.OnUserCommand( [ command ], request_data ) print( f'Result: { result }' ) assert_that( result, exception )
def LanguageServerCompleter_GetCompletions_NullNoError_test( app ): completer = MockCompleter() request_data = RequestWrap( BuildRequest() ) complete_response = { 'result': None } resolve_responses = [] with patch.object( completer, '_ServerIsInitialized', return_value = True ): with patch.object( completer, '_is_completion_provider', return_value = True ): with patch.object( completer.GetConnection(), 'GetResponse', side_effect = [ complete_response ] + resolve_responses ): assert_that( completer.ComputeCandidatesInner( request_data, 1 ), contains_exactly( empty(), False ) )
def LanguageServerCompleter_GetCompletions_List_test( app ): completer = MockCompleter() request_data = RequestWrap( BuildRequest() ) completion_response = { 'result': [ { 'label': 'test' } ] } resolve_responses = [ { 'result': { 'label': 'test' } }, ] with patch.object( completer, '_is_completion_provider', True ): with patch.object( completer.GetConnection(), 'GetResponse', side_effect = [ completion_response ] + resolve_responses ): assert_that( completer.ComputeCandidatesInner( request_data, 1 ), contains_exactly( has_items( has_entries( { 'insertion_text': 'test' } ) ), False ) )
def LanguageServerCompleter_GetCompletions_UnsupportedKinds_test( app ): completer = MockCompleter() request_data = RequestWrap( BuildRequest() ) completion_response = { 'result': [ { 'label': 'test', 'kind': len( lsp.ITEM_KIND ) + 1 } ] } resolve_responses = [ { 'result': { 'label': 'test' } }, ] with patch.object( completer, '_is_completion_provider', True ): with patch.object( completer.GetConnection(), 'GetResponse', side_effect = [ completion_response ] + resolve_responses ): assert_that( completer.ComputeCandidatesInner( request_data, 1 ), contains_exactly( has_items( all_of( has_entry( 'insertion_text', 'test' ), is_not( has_key( 'kind' ) ) ) ), False ) )
def LanguageServerCompleter_GetCompletions_CompleteOnCurrentColumn_test( app ): completer = MockCompleter() completer._resolve_completion_items = False a_response = { 'result': { 'items': [ { 'label': 'aba' }, { 'label': 'aab' }, { 'label': 'aaa' } ], 'isIncomplete': True } } aa_response = { 'result': { 'items': [ { 'label': 'aab' }, { 'label': 'aaa' } ], 'isIncomplete': False } } aaa_response = { 'result': { 'items': [ { 'label': 'aaa' } ], 'isIncomplete': False } } ab_response = { 'result': { 'items': [ { 'label': 'abb' }, { 'label': 'aba' } ], 'isIncomplete': False } } with patch.object( completer, '_is_completion_provider', True ): # User starts by typing the character "a". request_data = RequestWrap( BuildRequest( column_num = 2, contents = 'a', force_semantic = True ) ) with patch.object( completer.GetConnection(), 'GetResponse', return_value = a_response ) as response: assert_that( completer.ComputeCandidates( request_data ), contains_exactly( has_entry( 'insertion_text', 'aaa' ), has_entry( 'insertion_text', 'aab' ), has_entry( 'insertion_text', 'aba' ) ) ) # Nothing cached yet. assert_that( response.call_count, equal_to( 1 ) ) # User types again the character "a". request_data = RequestWrap( BuildRequest( column_num = 3, contents = 'aa', force_semantic = True ) ) with patch.object( completer.GetConnection(), 'GetResponse', return_value = aa_response ) as response: assert_that( completer.ComputeCandidates( request_data ), contains_exactly( has_entry( 'insertion_text', 'aaa' ), has_entry( 'insertion_text', 'aab' ) ) ) # The server returned an incomplete list of completions the first time so # a new completion request should have been sent. assert_that( response.call_count, equal_to( 1 ) ) # User types the character "a" a third time. request_data = RequestWrap( BuildRequest( column_num = 4, contents = 'aaa', force_semantic = True ) ) with patch.object( completer.GetConnection(), 'GetResponse', return_value = aaa_response ) as response: assert_that( completer.ComputeCandidates( request_data ), contains_exactly( has_entry( 'insertion_text', 'aaa' ) ) ) # The server returned a complete list of completions the second time and # the new query is a prefix of the cached one ("aa" is a prefix of "aaa") # so the cache should be used. assert_that( response.call_count, equal_to( 0 ) ) # User deletes the third character. request_data = RequestWrap( BuildRequest( column_num = 3, contents = 'aa', force_semantic = True ) ) with patch.object( completer.GetConnection(), 'GetResponse', return_value = aa_response ) as response: assert_that( completer.ComputeCandidates( request_data ), contains_exactly( has_entry( 'insertion_text', 'aaa' ), has_entry( 'insertion_text', 'aab' ) ) ) # The new query is still a prefix of the cached one ("aa" is a prefix of # "aa") so the cache should again be used. assert_that( response.call_count, equal_to( 0 ) ) # User deletes the second character. request_data = RequestWrap( BuildRequest( column_num = 2, contents = 'a', force_semantic = True ) ) with patch.object( completer.GetConnection(), 'GetResponse', return_value = a_response ) as response: assert_that( completer.ComputeCandidates( request_data ), contains_exactly( has_entry( 'insertion_text', 'aaa' ), has_entry( 'insertion_text', 'aab' ), has_entry( 'insertion_text', 'aba' ) ) ) # The new query is not anymore a prefix of the cached one ("aa" is not a # prefix of "a") so the cache is invalidated and a new request is sent. assert_that( response.call_count, equal_to( 1 ) ) # Finally, user inserts the "b" character. request_data = RequestWrap( BuildRequest( column_num = 3, contents = 'ab', force_semantic = True ) ) with patch.object( completer.GetConnection(), 'GetResponse', return_value = ab_response ) as response: assert_that( completer.ComputeCandidates( request_data ), contains_exactly( has_entry( 'insertion_text', 'aba' ), has_entry( 'insertion_text', 'abb' ) ) ) # Last response was incomplete so the cache should not be used. assert_that( response.call_count, equal_to( 1 ) )