1be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorcimport gc
2be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorcimport os
3be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc
4fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorcfrom clang.cindex import CursorKind
5fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorcfrom clang.cindex import Cursor
60f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorcfrom clang.cindex import File
7fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorcfrom clang.cindex import Index
80f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorcfrom clang.cindex import SourceLocation
90f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorcfrom clang.cindex import SourceRange
10fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorcfrom clang.cindex import TranslationUnitSaveError
11fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorcfrom clang.cindex import TranslationUnit
12fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorcfrom .util import get_cursor
13fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorcfrom .util import get_tu
1430c0f2637c4ba5d8764ff6e1ee6cbc89b89c63dbDaniel Dunbar
1530c0f2637c4ba5d8764ff6e1ee6cbc89b89c63dbDaniel DunbarkInputsDir = os.path.join(os.path.dirname(__file__), 'INPUTS')
1630c0f2637c4ba5d8764ff6e1ee6cbc89b89c63dbDaniel Dunbar
1730c0f2637c4ba5d8764ff6e1ee6cbc89b89c63dbDaniel Dunbardef test_spelling():
1830c0f2637c4ba5d8764ff6e1ee6cbc89b89c63dbDaniel Dunbar    path = os.path.join(kInputsDir, 'hello.cpp')
19fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    tu = TranslationUnit.from_source(path)
20a33dca490ad55c6f4bfc38a911f41a66f508a482Daniel Dunbar    assert tu.spelling == path
211b945a7455e17fd792ef3bd3790dc88beea5faadDaniel Dunbar
221b945a7455e17fd792ef3bd3790dc88beea5faadDaniel Dunbardef test_cursor():
231b945a7455e17fd792ef3bd3790dc88beea5faadDaniel Dunbar    path = os.path.join(kInputsDir, 'hello.cpp')
24fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    tu = get_tu(path)
251b945a7455e17fd792ef3bd3790dc88beea5faadDaniel Dunbar    c = tu.cursor
261b945a7455e17fd792ef3bd3790dc88beea5faadDaniel Dunbar    assert isinstance(c, Cursor)
27a6a6499a904441fc9e82ba9dd4155b8bc33f38f9Daniel Dunbar    assert c.kind is CursorKind.TRANSLATION_UNIT
281f8d7f94c7c61c7bb45ebb07e6ce5461bf2a80d5Daniel Dunbar
291f8d7f94c7c61c7bb45ebb07e6ce5461bf2a80d5Daniel Dunbardef test_parse_arguments():
301f8d7f94c7c61c7bb45ebb07e6ce5461bf2a80d5Daniel Dunbar    path = os.path.join(kInputsDir, 'parse_arguments.c')
31fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    tu = TranslationUnit.from_source(path, ['-DDECL_ONE=hello', '-DDECL_TWO=hi'])
321f8d7f94c7c61c7bb45ebb07e6ce5461bf2a80d5Daniel Dunbar    spellings = [c.spelling for c in tu.cursor.get_children()]
331f8d7f94c7c61c7bb45ebb07e6ce5461bf2a80d5Daniel Dunbar    assert spellings[-2] == 'hello'
341f8d7f94c7c61c7bb45ebb07e6ce5461bf2a80d5Daniel Dunbar    assert spellings[-1] == 'hi'
355b534f67946eeb2cb29076288bfee9707f055f82Daniel Dunbar
36265e6b2d17ae348ce73961866979f574c65b56f4Tobias Grosserdef test_reparse_arguments():
37265e6b2d17ae348ce73961866979f574c65b56f4Tobias Grosser    path = os.path.join(kInputsDir, 'parse_arguments.c')
38fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    tu = TranslationUnit.from_source(path, ['-DDECL_ONE=hello', '-DDECL_TWO=hi'])
39265e6b2d17ae348ce73961866979f574c65b56f4Tobias Grosser    tu.reparse()
40265e6b2d17ae348ce73961866979f574c65b56f4Tobias Grosser    spellings = [c.spelling for c in tu.cursor.get_children()]
41265e6b2d17ae348ce73961866979f574c65b56f4Tobias Grosser    assert spellings[-2] == 'hello'
42265e6b2d17ae348ce73961866979f574c65b56f4Tobias Grosser    assert spellings[-1] == 'hi'
43265e6b2d17ae348ce73961866979f574c65b56f4Tobias Grosser
445b534f67946eeb2cb29076288bfee9707f055f82Daniel Dunbardef test_unsaved_files():
45fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    tu = TranslationUnit.from_source('fake.c', ['-I./'], unsaved_files = [
465b534f67946eeb2cb29076288bfee9707f055f82Daniel Dunbar            ('fake.c', """
4788f9c6ca6eb0d4c48687dfed4d94292209c5a919Tobias Grosser#include "fake.h"
485b534f67946eeb2cb29076288bfee9707f055f82Daniel Dunbarint x;
495b534f67946eeb2cb29076288bfee9707f055f82Daniel Dunbarint SOME_DEFINE;
505b534f67946eeb2cb29076288bfee9707f055f82Daniel Dunbar"""),
5188f9c6ca6eb0d4c48687dfed4d94292209c5a919Tobias Grosser            ('./fake.h', """
525b534f67946eeb2cb29076288bfee9707f055f82Daniel Dunbar#define SOME_DEFINE y
535b534f67946eeb2cb29076288bfee9707f055f82Daniel Dunbar""")
545b534f67946eeb2cb29076288bfee9707f055f82Daniel Dunbar            ])
555b534f67946eeb2cb29076288bfee9707f055f82Daniel Dunbar    spellings = [c.spelling for c in tu.cursor.get_children()]
565b534f67946eeb2cb29076288bfee9707f055f82Daniel Dunbar    assert spellings[-2] == 'x'
575b534f67946eeb2cb29076288bfee9707f055f82Daniel Dunbar    assert spellings[-1] == 'y'
58db59a7700e5e42e8b5f6f8e327067a969540ee14Daniel Dunbar
59db59a7700e5e42e8b5f6f8e327067a969540ee14Daniel Dunbardef test_unsaved_files_2():
60db59a7700e5e42e8b5f6f8e327067a969540ee14Daniel Dunbar    import StringIO
61fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    tu = TranslationUnit.from_source('fake.c', unsaved_files = [
62db59a7700e5e42e8b5f6f8e327067a969540ee14Daniel Dunbar            ('fake.c', StringIO.StringIO('int x;'))])
63db59a7700e5e42e8b5f6f8e327067a969540ee14Daniel Dunbar    spellings = [c.spelling for c in tu.cursor.get_children()]
64db59a7700e5e42e8b5f6f8e327067a969540ee14Daniel Dunbar    assert spellings[-1] == 'x'
65ef7f798c0921cde7e665935a5630578cc1065e0fDaniel Dunbar
668be80e1e6effd5a333bc70e7f030dc9397d0554eDouglas Gregordef normpaths_equal(path1, path2):
678be80e1e6effd5a333bc70e7f030dc9397d0554eDouglas Gregor    """ Compares two paths for equality after normalizing them with
688be80e1e6effd5a333bc70e7f030dc9397d0554eDouglas Gregor        os.path.normpath
698be80e1e6effd5a333bc70e7f030dc9397d0554eDouglas Gregor    """
708be80e1e6effd5a333bc70e7f030dc9397d0554eDouglas Gregor    return os.path.normpath(path1) == os.path.normpath(path2)
71ef7f798c0921cde7e665935a5630578cc1065e0fDaniel Dunbar
72ef7f798c0921cde7e665935a5630578cc1065e0fDaniel Dunbardef test_includes():
73ef7f798c0921cde7e665935a5630578cc1065e0fDaniel Dunbar    def eq(expected, actual):
74ef7f798c0921cde7e665935a5630578cc1065e0fDaniel Dunbar        if not actual.is_input_file:
758be80e1e6effd5a333bc70e7f030dc9397d0554eDouglas Gregor            return  normpaths_equal(expected[0], actual.source.name) and \
768be80e1e6effd5a333bc70e7f030dc9397d0554eDouglas Gregor                    normpaths_equal(expected[1], actual.include.name)
77ef7f798c0921cde7e665935a5630578cc1065e0fDaniel Dunbar        else:
788be80e1e6effd5a333bc70e7f030dc9397d0554eDouglas Gregor            return normpaths_equal(expected[1], actual.include.name)
79ef7f798c0921cde7e665935a5630578cc1065e0fDaniel Dunbar
80ef7f798c0921cde7e665935a5630578cc1065e0fDaniel Dunbar    src = os.path.join(kInputsDir, 'include.cpp')
81ef7f798c0921cde7e665935a5630578cc1065e0fDaniel Dunbar    h1 = os.path.join(kInputsDir, "header1.h")
82ef7f798c0921cde7e665935a5630578cc1065e0fDaniel Dunbar    h2 = os.path.join(kInputsDir, "header2.h")
83ef7f798c0921cde7e665935a5630578cc1065e0fDaniel Dunbar    h3 = os.path.join(kInputsDir, "header3.h")
848be80e1e6effd5a333bc70e7f030dc9397d0554eDouglas Gregor    inc = [(src, h1), (h1, h3), (src, h2), (h2, h3)]
85ef7f798c0921cde7e665935a5630578cc1065e0fDaniel Dunbar
86fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    tu = TranslationUnit.from_source(src)
87ef7f798c0921cde7e665935a5630578cc1065e0fDaniel Dunbar    for i in zip(inc, tu.get_includes()):
88ef7f798c0921cde7e665935a5630578cc1065e0fDaniel Dunbar        assert eq(i[0], i[1])
89fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
90fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorcdef save_tu(tu):
91fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    """Convenience API to save a TranslationUnit to a file.
92fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
93fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    Returns the filename it was saved to.
94fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    """
95fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
96fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    # FIXME Generate a temp file path using system APIs.
97fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    base = 'TEMP_FOR_TRANSLATIONUNIT_SAVE.c'
98fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    path = os.path.join(kInputsDir, base)
99fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
100fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    # Just in case.
101fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    if os.path.exists(path):
102fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc        os.unlink(path)
103fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
104fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    tu.save(path)
105fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
106fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    return path
107fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
108fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorcdef test_save():
109fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    """Ensure TranslationUnit.save() works."""
110fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
111fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    tu = get_tu('int foo();')
112fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
113fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    path = save_tu(tu)
114fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    assert os.path.exists(path)
115fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    assert os.path.getsize(path) > 0
116fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    os.unlink(path)
117fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
118fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorcdef test_save_translation_errors():
119fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    """Ensure that saving to an invalid directory raises."""
120fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
121fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    tu = get_tu('int foo();')
122fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
123fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    path = '/does/not/exist/llvm-test.ast'
124fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    assert not os.path.exists(os.path.dirname(path))
125fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
126fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    try:
127fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc        tu.save(path)
128fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc        assert False
129fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    except TranslationUnitSaveError as ex:
130fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc        expected = TranslationUnitSaveError.ERROR_UNKNOWN
131fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc        assert ex.save_error == expected
132fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
133fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorcdef test_load():
134fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    """Ensure TranslationUnits can be constructed from saved files."""
135fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
136fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    tu = get_tu('int foo();')
137fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    assert len(tu.diagnostics) == 0
138fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    path = save_tu(tu)
139fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
140fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    assert os.path.exists(path)
141fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    assert os.path.getsize(path) > 0
142fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
143fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    tu2 = TranslationUnit.from_ast_file(filename=path)
144fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    assert len(tu2.diagnostics) == 0
145fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
146fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    foo = get_cursor(tu2, 'foo')
147fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    assert foo is not None
148fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
149fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    # Just in case there is an open file descriptor somewhere.
150fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    del tu2
151fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
152fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    os.unlink(path)
153fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc
154fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorcdef test_index_parse():
155fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    path = os.path.join(kInputsDir, 'hello.cpp')
156fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    index = Index.create()
157fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    tu = index.parse(path)
158fbf620bc2b7812e826f04befa31d3a48a86210baGregory Szorc    assert isinstance(tu, TranslationUnit)
1590f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc
1600f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorcdef test_get_file():
1610f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    """Ensure tu.get_file() works appropriately."""
1620f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc
1630f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    tu = get_tu('int foo();')
1640f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc
1650f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    f = tu.get_file('t.c')
1660f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert isinstance(f, File)
1670f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert f.name == 't.c'
1680f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc
1690f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    try:
1700f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc        f = tu.get_file('foobar.cpp')
1710f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    except:
1720f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc        pass
1730f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    else:
1740f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc        assert False
1750f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc
1760f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorcdef test_get_source_location():
1770f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    """Ensure tu.get_source_location() works."""
1780f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc
1790f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    tu = get_tu('int foo();')
1800f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc
1810f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    location = tu.get_location('t.c', 2)
1820f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert isinstance(location, SourceLocation)
1830f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert location.offset == 2
1840f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert location.file.name == 't.c'
1850f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc
1860f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    location = tu.get_location('t.c', (1, 3))
1870f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert isinstance(location, SourceLocation)
1880f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert location.line == 1
1890f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert location.column == 3
1900f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert location.file.name == 't.c'
1910f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc
1920f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorcdef test_get_source_range():
1930f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    """Ensure tu.get_source_range() works."""
1940f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc
1950f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    tu = get_tu('int foo();')
1960f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc
1970f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    r = tu.get_extent('t.c', (1,4))
1980f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert isinstance(r, SourceRange)
1990f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert r.start.offset == 1
2000f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert r.end.offset == 4
2010f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert r.start.file.name == 't.c'
2020f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert r.end.file.name == 't.c'
2030f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc
2040f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    r = tu.get_extent('t.c', ((1,2), (1,3)))
2050f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert isinstance(r, SourceRange)
2060f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert r.start.line == 1
2070f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert r.start.column == 2
2080f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert r.end.line == 1
2090f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert r.end.column == 3
2100f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert r.start.file.name == 't.c'
2110f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert r.end.file.name == 't.c'
2120f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc
2130f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    start = tu.get_location('t.c', 0)
2140f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    end = tu.get_location('t.c', 5)
2150f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc
2160f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    r = tu.get_extent('t.c', (start, end))
2170f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert isinstance(r, SourceRange)
2180f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert r.start.offset == 0
2190f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert r.end.offset == 5
2200f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert r.start.file.name == 't.c'
2210f1964a5c1627bcc3fd658cdd1f139e30b0ad612Gregory Szorc    assert r.end.file.name == 't.c'
222be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc
223be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorcdef test_get_tokens_gc():
224be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc    """Ensures get_tokens() works properly with garbage collection."""
225be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc
226be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc    tu = get_tu('int foo();')
227be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc    r = tu.get_extent('t.c', (0, 10))
228be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc    tokens = list(tu.get_tokens(extent=r))
229be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc
230be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc    assert tokens[0].spelling == 'int'
231be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc    gc.collect()
232be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc    assert tokens[0].spelling == 'int'
233be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc
234be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc    del tokens[1]
235be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc    gc.collect()
236be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc    assert tokens[0].spelling == 'int'
237be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc
238be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc    # May trigger segfault if we don't do our job properly.
239be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc    del tokens
240be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc    gc.collect()
241be51e43ba2c57b8032286af4e8713485b6dc78c3Gregory Szorc    gc.collect() # Just in case.
242