Exemplo n.º 1
0
def GetCompletions_MoreThan10_NoResolve_ThenResolveCacheBad_test(app):
    ClearCompletionsCache()
    request, response = RunTest(
        app,
        {
            'description':
            "More than 10 candiates after filtering, don't resolve",
            'request': {
                'filetype': 'java',
                'filepath': ProjectPath('MethodsWithDocumentation.java'),
                'line_num': 33,
                'column_num': 7,
            },
            'expect': {
                'response':
                requests.codes.ok,
                'data':
                has_entries({
                    'completions':
                    has_item(
                        CompletionEntryMatcher(
                            'useAString',
                            'MethodsWithDocumentation.useAString(String s) : void',
                            {
                                'kind':
                                'Method',
                                # This is the un-resolved info (no documentation)
                                'detailed_info':
                                'useAString(String s) : void\n\n',
                                'extra_data':
                                has_entries({'resolve': instance_of(int)})
                            }), ),
                    'completion_start_column':
                    7,
                    'errors':
                    empty(),
                })
            },
        })

    # We know the item we want is there, pull out the resolve ID
    resolve = None
    for item in response['completions']:
        if item['insertion_text'] == 'useAString':
            resolve = item['extra_data']['resolve']
            break

    assert resolve is not None

    request['resolve'] = resolve
    # Use a different position - should mean the cache is not valid for request
    request['column_num'] = 20
    response = app.post_json('/resolve_completion', request).json

    print(f"Resolve response: { pformat( response ) }")

    assert_that(
        response,
        has_entries({
            'completion':
            None,
            'errors':
            contains_exactly(ErrorMatcher(CompletionsChanged))
        }))
Exemplo n.º 2
0
    # We ignore errors here and we check the response code ourself.
    # This is to allow testing of requests returning errors.
    request = CombineRequest(test['request'], {'contents': contents})
    response = app.post_json('/completions', request, expect_errors=True)

    print(f'completer response: { pformat( response.json ) }')

    assert_that(response.status_code, equal_to(test['expect']['response']))

    assert_that(response.json, test['expect']['data'])

    return request, response.json


PUBLIC_OBJECT_METHODS = [
    CompletionEntryMatcher('equals', 'Object.equals(Object arg0) : boolean',
                           {'kind': 'Method'}),
    CompletionEntryMatcher('getClass', 'Object.getClass() : Class<?>',
                           {'kind': 'Method'}),
    CompletionEntryMatcher('hashCode', 'Object.hashCode() : int',
                           {'kind': 'Method'}),
    CompletionEntryMatcher('notify', 'Object.notify() : void',
                           {'kind': 'Method'}),
    CompletionEntryMatcher('notifyAll', 'Object.notifyAll() : void',
                           {'kind': 'Method'}),
    CompletionEntryMatcher('toString', 'Object.toString() : String',
                           {'kind': 'Method'}),
    CompletionEntryMatcher(
        'wait', 'Object.wait(long arg0, int arg1) : void', {
            'menu_text': matches_regexp('wait\\(long .*, int .*\\) : void'),
            'kind': 'Method',
        }),
Exemplo n.º 3
0
def GetCompletions_MoreThan10_NoResolve_ThenResolve_test(app):
    ClearCompletionsCache()
    request, response = RunTest(
        app,
        {
            'description':
            "More than 10 candiates after filtering, don't resolve",
            'request': {
                'filetype': 'java',
                'filepath': ProjectPath('MethodsWithDocumentation.java'),
                'line_num': 33,
                'column_num': 7,
            },
            'expect': {
                'response':
                requests.codes.ok,
                'data':
                has_entries({
                    'completions':
                    has_item(
                        CompletionEntryMatcher(
                            'useAString',
                            'MethodsWithDocumentation.useAString(String s) : void',
                            {
                                'kind':
                                'Method',
                                # This is the un-resolved info (no documentation)
                                'detailed_info':
                                'useAString(String s) : void\n\n',
                                'extra_data':
                                has_entries({'resolve': instance_of(int)})
                            }), ),
                    'completion_start_column':
                    7,
                    'errors':
                    empty(),
                })
            },
        })

    # We know the item we want is there, pull out the resolve ID
    resolve = None
    for item in response['completions']:
        if item['insertion_text'] == 'useAString':
            resolve = item['extra_data']['resolve']
            break

    assert resolve is not None

    request['resolve'] = resolve
    # Do this twice to prove that the request is idempotent
    for i in range(2):
        response = app.post_json('/resolve_completion', request).json

        print(f"Resolve response: { pformat( response ) }")

        nl = os.linesep
        assert_that(
            response,
            has_entries({
                'completion':
                CompletionEntryMatcher(
                    'useAString',
                    'MethodsWithDocumentation.useAString(String s) : void',
                    {
                        'kind':
                        'Method',
                        # This is the resolved info (no documentation)
                        'detailed_info':
                        'useAString(String s) : void\n'
                        '\n'
                        f'Multiple lines of description here.{ nl }'
                        f'{ nl }'
                        f' *  **Parameters:**{ nl }'
                        f'    { nl }'
                        f'     *  **s** a string'
                    }),
                'errors':
                empty(),
            }))

        # The item is resoled
        assert_that(response['completion'], is_not(has_key('resolve')))
        assert_that(response['completion'], is_not(has_key('item')))
Exemplo n.º 4
0
def GetCompletions_ClientDataGivenToExtraConf_Cache_test(app):
    app.post_json(
        '/load_extra_conf_file',
        {'filepath': PathToTestFile('client_data', '.ycm_extra_conf.py')})

    filepath = PathToTestFile('client_data', 'macro.cpp')
    contents = ReadFile(filepath)
    request = {
        'filetype': 'cpp',
        'filepath': filepath,
        'contents': contents,
        'line_num': 11,
        'column_num': 8
    }

    # Complete with flags from the client.
    completion_request = CombineRequest(
        request, {'extra_conf_data': {
            'flags': ['-DSOME_MACRO']
        }})

    assert_that(
        app.post_json('/completions', completion_request).json,
        has_entries({
            'completions':
            has_item(CompletionEntryMatcher('macro_defined')),
            'errors':
            empty()
        }))

    # Complete at the same position but for a different set of flags from the
    # client.
    completion_request = CombineRequest(
        request, {'extra_conf_data': {
            'flags': ['-Wall']
        }})

    assert_that(
        app.post_json('/completions', completion_request).json,
        has_entries({
            'completions':
            has_item(CompletionEntryMatcher('macro_not_defined')),
            'errors':
            empty()
        }))

    # Finally, complete once again at the same position but no flags are given by
    # the client. An empty list of flags is returned by the extra conf file in
    # that case.
    completion_request = CombineRequest(request, {})

    assert_that(
        app.post_json('/completions', completion_request).json,
        has_entries({
            'completions':
            empty(),
            'errors':
            contains(
                ErrorMatcher(RuntimeError,
                             'Still no compile flags, no completions yet.'))
        }))
Exemplo n.º 5
0
  # This is to allow testing of requests returning errors.
  response = app.post_json( '/completions',
                            CombineRequest( test[ 'request' ], {
                              'contents': contents
                            } ),
                            expect_errors = True )

  print( 'completer response: {0}'.format( pformat( response.json ) ) )

  eq_( response.status_code, test[ 'expect' ][ 'response' ] )

  assert_that( response.json, test[ 'expect' ][ 'data' ] )


PUBLIC_OBJECT_METHODS = [
  CompletionEntryMatcher( 'equals', 'Object', { 'kind': 'Method' } ),
  CompletionEntryMatcher( 'getClass', 'Object', { 'kind': 'Method' } ),
  CompletionEntryMatcher( 'hashCode', 'Object', { 'kind': 'Method' } ),
  CompletionEntryMatcher( 'notify', 'Object', { 'kind': 'Method' } ),
  CompletionEntryMatcher( 'notifyAll', 'Object', { 'kind': 'Method' } ),
  CompletionEntryMatcher( 'toString', 'Object', { 'kind': 'Method' } ),
  CompletionEntryMatcher( 'wait', 'Object', {
    'menu_text': matches_regexp( 'wait\\(long .*, int .*\\) : void' ),
    'kind': 'Method',
  } ),
  CompletionEntryMatcher( 'wait', 'Object', {
    'menu_text': matches_regexp( 'wait\\(long .*\\) : void' ),
    'kind': 'Method',
  } ),
  CompletionEntryMatcher( 'wait', 'Object', {
    'menu_text': 'wait() : void',
Exemplo n.º 6
0
def GetCompletions_SupportExtraConf_test(app):
    RunTest(
        app, {
            'description': 'Flags for foo.cpp from extra conf file are used',
            'request': {
                'filetype': 'cpp',
                'filepath': PathToTestFile('extra_conf', 'foo.cpp'),
                'line_num': 5,
                'column_num': 15
            },
            'expect': {
                'response':
                requests.codes.ok,
                'data':
                has_entries({
                    'completion_start_column':
                    15,
                    'completions':
                    contains_exactly(CompletionEntryMatcher('member_foo')),
                    'errors':
                    empty(),
                })
            }
        })

    RunTest(
        app, {
            'description': 'Same flags are used again for foo.cpp',
            'request': {
                'filetype': 'cpp',
                'filepath': PathToTestFile('extra_conf', 'foo.cpp'),
                'line_num': 5,
                'column_num': 15
            },
            'expect': {
                'response':
                requests.codes.ok,
                'data':
                has_entries({
                    'completion_start_column':
                    15,
                    'completions':
                    contains_exactly(CompletionEntryMatcher('member_foo')),
                    'errors':
                    empty(),
                })
            }
        })

    RunTest(
        app, {
            'description': 'Flags for bar.cpp from extra conf file are used',
            'request': {
                'filetype': 'cpp',
                'filepath': PathToTestFile('extra_conf', 'bar.cpp'),
                'line_num': 5,
                'column_num': 15
            },
            'expect': {
                'response':
                requests.codes.ok,
                'data':
                has_entries({
                    'completion_start_column':
                    15,
                    'completions':
                    contains_exactly(CompletionEntryMatcher('member_bar')),
                    'errors':
                    empty(),
                })
            }
        })
Exemplo n.º 7
0
def GetCompletions_IncludeMultiFileType_test(app):
    trivial1 = {
        'filetypes': ['python', 'javascript'],
        'contents': ReadFile(PathToTestFile('trivial.js')),
    }
    trivial2 = {
        'filetypes': ['javascript'],
        'contents': ReadFile(PathToTestFile('trivial2.js')),
    }

    request = {
        'line_num': 1,
        'column_num': 3,
        'file_data': {
            PathToTestFile('trivial.js'): trivial1,
            PathToTestFile('trivial2.js'): trivial2,
        },
    }

    app.post_json(
        '/event_notification',
        CombineRequest(
            request, {
                'filepath': PathToTestFile('trivial2.js'),
                'event_name': 'FileReadyToParse',
            }))

    response = app.post_json(
        '/completions',
        CombineRequest(
            request,
            {
                'filepath': PathToTestFile('trivial2.js'),
                # We must force the use of semantic engine because the previous test would
                # have entered 'empty' results into the completion cache.
                'force_semantic': True,
            })).json

    print('completer response: {0}'.format(pformat(response, indent=2)))

    assert_that(
        response,
        has_entries({
            'completion_start_column':
            3,
            # Note: This time, we *do* see the completions, becuase one of the 2
            # filetypes for trivial.js is javascript.
            'completions':
            contains_inanyorder(
                CompletionEntryMatcher('y', 'string'),
                CompletionEntryMatcher('z', 'string'),
                CompletionEntryMatcher('toString', 'fn() -> string'),
                CompletionEntryMatcher('toLocaleString', 'fn() -> string'),
                CompletionEntryMatcher('valueOf', 'fn() -> number'),
                CompletionEntryMatcher('hasOwnProperty',
                                       'fn(prop: string) -> bool'),
                CompletionEntryMatcher('isPrototypeOf', 'fn(obj: ?) -> bool'),
                CompletionEntryMatcher('propertyIsEnumerable',
                                       'fn(prop: string) -> bool'),
            ),
            'errors':
            empty(),
        }))
Exemplo n.º 8
0
    def test_GetCompletions_Basic(self, app):
        RunTest(
            app, {
                'description':
                'Extra and detailed info when completions are methods',
                'request': {
                    'line_num': 17,
                    'column_num': 6,
                    'filepath': PathToTestFile('test.ts')
                },
                'expect': {
                    'response':
                    requests.codes.ok,
                    'data':
                    has_entries({
                        'completions':
                        contains_inanyorder(
                            CompletionEntryMatcher(
                                'methodA',
                                '(method) Foo.methodA(): void',
                                extra_params={
                                    'kind':
                                    'method',
                                    'detailed_info':
                                    '(method) Foo.methodA(): void\n\n'
                                    'Unicode string: 说话'
                                }),
                            CompletionEntryMatcher(
                                'methodB',
                                '(method) Foo.methodB(): void',
                                extra_params={
                                    'kind': 'method',
                                    'detailed_info':
                                    '(method) Foo.methodB(): void'
                                }),
                            CompletionEntryMatcher(
                                'methodC',
                                '(method) Foo.methodC(a: { foo: string; bar: number; }): void',
                                extra_params={
                                    'kind':
                                    'method',
                                    'detailed_info':
                                    '(method) Foo.methodC(a: {\n'
                                    '    foo: string;\n'
                                    '    bar: number;\n'
                                    '}): void'
                                }))
                    })
                }
            })

        RunTest(
            app, {
                'description': 'Filtering works',
                'request': {
                    'line_num': 17,
                    'column_num': 7,
                    'filepath': PathToTestFile('test.ts')
                },
                'expect': {
                    'response':
                    requests.codes.ok,
                    'data':
                    has_entries({
                        'completions':
                        contains_inanyorder(
                            CompletionEntryMatcher(
                                'methodA',
                                '(method) Foo.methodA(): void',
                                extra_params={
                                    'kind':
                                    'method',
                                    'detailed_info':
                                    '(method) Foo.methodA(): void\n\n'
                                    'Unicode string: 说话'
                                }))
                    })
                }
            })
def EventNotification_OnBufferUnload_CloseFile_test(app):
    # Open main.ts file in a buffer.
    main_filepath = PathToTestFile('buffer_unload', 'main.ts')
    main_contents = ReadFile(main_filepath)

    event_data = BuildRequest(filepath=main_filepath,
                              filetype='typescript',
                              contents=main_contents,
                              event_name='BufferVisit')
    app.post_json('/event_notification', event_data)

    # Complete in main.ts buffer an object defined in imported.ts.
    completion_data = BuildRequest(filepath=main_filepath,
                                   filetype='typescript',
                                   contents=main_contents,
                                   line_num=3,
                                   column_num=10)
    response = app.post_json('/completions', completion_data)
    assert_that(
        response.json,
        has_entries({
            'completions':
            contains_exactly(CompletionEntryMatcher('method'))
        }))

    # Open imported.ts file in another buffer.
    imported_filepath = PathToTestFile('buffer_unload', 'imported.ts')
    imported_contents = ReadFile(imported_filepath)

    event_data = BuildRequest(filepath=imported_filepath,
                              filetype='typescript',
                              contents=imported_contents,
                              event_name='BufferVisit')
    app.post_json('/event_notification', event_data)

    # Modify imported.ts buffer without writing the changes to disk.
    modified_imported_contents = imported_contents.replace(
        'method', 'modified_method')

    # FIXME: TypeScript completer should not rely on the FileReadyToParse events
    # to synchronize the contents of dirty buffers but use instead the file_data
    # field of the request.
    event_data = BuildRequest(filepath=imported_filepath,
                              filetype='typescript',
                              contents=modified_imported_contents,
                              event_name='FileReadyToParse')
    app.post_json('/event_notification', event_data)

    # Complete at same location in main.ts buffer.
    imported_data = {
        imported_filepath: {
            'filetypes': ['typescript'],
            'contents': modified_imported_contents
        }
    }
    completion_data = BuildRequest(filepath=main_filepath,
                                   filetype='typescript',
                                   contents=main_contents,
                                   line_num=3,
                                   column_num=10,
                                   file_data=imported_data)
    response = app.post_json('/completions', completion_data)
    assert_that(
        response.json,
        has_entries({
            'completions':
            contains_exactly(CompletionEntryMatcher('modified_method'))
        }))

    # Unload imported.ts buffer.
    event_data = BuildRequest(filepath=imported_filepath,
                              filetype='typescript',
                              contents=imported_contents,
                              event_name='BufferUnload')
    app.post_json('/event_notification', event_data)

    # Complete at same location in main.ts buffer.
    completion_data = BuildRequest(filepath=main_filepath,
                                   filetype='typescript',
                                   contents=main_contents,
                                   line_num=3,
                                   column_num=10)
    response = app.post_json('/completions', completion_data)
    assert_that(
        response.json,
        has_entries({
            'completions':
            contains_exactly(CompletionEntryMatcher('method'))
        }))
Exemplo n.º 10
0
def GetCompletions_WithFixIt_test(app):
    filepath = ProjectPath('TestFactory.java')
    RunTest(
        app,
        {
            'description': 'semantic completion with when additional textEdit',
            'request': {
                'filetype': 'java',
                'filepath': filepath,
                'line_num': 19,
                'column_num': 25,
            },
            'expect': {
                'response':
                requests.codes.ok,
                'data':
                has_entries({
                    'completion_start_column':
                    22,
                    'completions':
                    contains_inanyorder(
                        CompletionEntryMatcher(
                            'CUTHBERT',
                            'com.test.wobble.Wibble',
                            {
                                'kind':
                                'Field',
                                'extra_data':
                                has_entries({
                                    'fixits':
                                    contains(
                                        has_entries({
                                            'chunks':
                                            contains(
                                                # For some reason, jdtls feels it's OK to replace the text
                                                # before the cursor. Perhaps it does this to canonicalise the
                                                # path ?
                                                ChunkMatcher(
                                                    'Wibble',
                                                    LocationMatcher(
                                                        filepath, 19, 15),
                                                    LocationMatcher(
                                                        filepath, 19, 21)),
                                                # When doing an import, eclipse likes to add two newlines
                                                # after the package. I suppose this is config in real eclipse,
                                                # but there's no mechanism to configure this in jdtl afaik.
                                                ChunkMatcher(
                                                    '\n\n',
                                                    LocationMatcher(
                                                        filepath, 1, 18),
                                                    LocationMatcher(
                                                        filepath, 1, 18)),
                                                # OK, so it inserts the import
                                                ChunkMatcher(
                                                    'import com.test.wobble.Wibble;',
                                                    LocationMatcher(
                                                        filepath, 1, 18),
                                                    LocationMatcher(
                                                        filepath, 1, 18)),
                                                # More newlines. Who doesn't like newlines?!
                                                ChunkMatcher(
                                                    '\n\n',
                                                    LocationMatcher(
                                                        filepath, 1, 18),
                                                    LocationMatcher(
                                                        filepath, 1, 18)),
                                                # For reasons known only to the eclipse JDT developers, it
                                                # seems to want to delete the lines after the package first.
                                                ChunkMatcher(
                                                    '',
                                                    LocationMatcher(
                                                        filepath, 1, 18),
                                                    LocationMatcher(
                                                        filepath, 3, 1)),
                                            ),
                                        })),
                                }),
                            }), ),
                    'errors':
                    empty(),
                })
            },
        })