Home | History | Annotate | Download | only in cindex
      1 import gc
      2 
      3 from clang.cindex import CursorKind
      4 from clang.cindex import TranslationUnit
      5 from clang.cindex import TypeKind
      6 from .util import get_cursor
      7 from .util import get_cursors
      8 from .util import get_tu
      9 
     10 kInput = """\
     11 // FIXME: Find nicer way to drop builtins and other cruft.
     12 int start_decl;
     13 
     14 struct s0 {
     15   int a;
     16   int b;
     17 };
     18 
     19 struct s1;
     20 
     21 void f0(int a0, int a1) {
     22   int l0, l1;
     23 
     24   if (a0)
     25     return;
     26 
     27   for (;;) {
     28     break;
     29   }
     30 }
     31 """
     32 
     33 def test_get_children():
     34     tu = get_tu(kInput)
     35 
     36     # Skip until past start_decl.
     37     it = tu.cursor.get_children()
     38     while it.next().spelling != 'start_decl':
     39         pass
     40 
     41     tu_nodes = list(it)
     42 
     43     assert len(tu_nodes) == 3
     44     for cursor in tu_nodes:
     45         assert cursor.translation_unit is not None
     46 
     47     assert tu_nodes[0] != tu_nodes[1]
     48     assert tu_nodes[0].kind == CursorKind.STRUCT_DECL
     49     assert tu_nodes[0].spelling == 's0'
     50     assert tu_nodes[0].is_definition() == True
     51     assert tu_nodes[0].location.file.name == 't.c'
     52     assert tu_nodes[0].location.line == 4
     53     assert tu_nodes[0].location.column == 8
     54     assert tu_nodes[0].hash > 0
     55     assert tu_nodes[0].translation_unit is not None
     56 
     57     s0_nodes = list(tu_nodes[0].get_children())
     58     assert len(s0_nodes) == 2
     59     assert s0_nodes[0].kind == CursorKind.FIELD_DECL
     60     assert s0_nodes[0].spelling == 'a'
     61     assert s0_nodes[0].type.kind == TypeKind.INT
     62     assert s0_nodes[1].kind == CursorKind.FIELD_DECL
     63     assert s0_nodes[1].spelling == 'b'
     64     assert s0_nodes[1].type.kind == TypeKind.INT
     65 
     66     assert tu_nodes[1].kind == CursorKind.STRUCT_DECL
     67     assert tu_nodes[1].spelling == 's1'
     68     assert tu_nodes[1].displayname == 's1'
     69     assert tu_nodes[1].is_definition() == False
     70 
     71     assert tu_nodes[2].kind == CursorKind.FUNCTION_DECL
     72     assert tu_nodes[2].spelling == 'f0'
     73     assert tu_nodes[2].displayname == 'f0(int, int)'
     74     assert tu_nodes[2].is_definition() == True
     75 
     76 def test_references():
     77     """Ensure that references to TranslationUnit are kept."""
     78     tu = get_tu('int x;')
     79     cursors = list(tu.cursor.get_children())
     80     assert len(cursors) > 0
     81 
     82     cursor = cursors[0]
     83     assert isinstance(cursor.translation_unit, TranslationUnit)
     84 
     85     # Delete reference to TU and perform a full GC.
     86     del tu
     87     gc.collect()
     88     assert isinstance(cursor.translation_unit, TranslationUnit)
     89 
     90     # If the TU was destroyed, this should cause a segfault.
     91     parent = cursor.semantic_parent
     92 
     93 def test_canonical():
     94     source = 'struct X; struct X; struct X { int member; };'
     95     tu = get_tu(source)
     96 
     97     cursors = []
     98     for cursor in tu.cursor.get_children():
     99         if cursor.spelling == 'X':
    100             cursors.append(cursor)
    101 
    102     assert len(cursors) == 3
    103     assert cursors[1].canonical == cursors[2].canonical
    104 
    105 def test_is_static_method():
    106     """Ensure Cursor.is_static_method works."""
    107 
    108     source = 'class X { static void foo(); void bar(); };'
    109     tu = get_tu(source, lang='cpp')
    110 
    111     cls = get_cursor(tu, 'X')
    112     foo = get_cursor(tu, 'foo')
    113     bar = get_cursor(tu, 'bar')
    114     assert cls is not None
    115     assert foo is not None
    116     assert bar is not None
    117 
    118     assert foo.is_static_method()
    119     assert not bar.is_static_method()
    120 
    121 def test_underlying_type():
    122     tu = get_tu('typedef int foo;')
    123     typedef = get_cursor(tu, 'foo')
    124     assert typedef is not None
    125 
    126     assert typedef.kind.is_declaration()
    127     underlying = typedef.underlying_typedef_type
    128     assert underlying.kind == TypeKind.INT
    129 
    130 kParentTest = """\
    131         class C {
    132             void f();
    133         }
    134 
    135         void C::f() { }
    136     """
    137 def test_semantic_parent():
    138     tu = get_tu(kParentTest, 'cpp')
    139     curs = get_cursors(tu, 'f')
    140     decl = get_cursor(tu, 'C')
    141     assert(len(curs) == 2)
    142     assert(curs[0].semantic_parent == curs[1].semantic_parent)
    143     assert(curs[0].semantic_parent == decl)
    144 
    145 def test_lexical_parent():
    146     tu = get_tu(kParentTest, 'cpp')
    147     curs = get_cursors(tu, 'f')
    148     decl = get_cursor(tu, 'C')
    149     assert(len(curs) == 2)
    150     assert(curs[0].lexical_parent != curs[1].lexical_parent)
    151     assert(curs[0].lexical_parent == decl)
    152     assert(curs[1].lexical_parent == tu.cursor)
    153 
    154 def test_enum_type():
    155     tu = get_tu('enum TEST { FOO=1, BAR=2 };')
    156     enum = get_cursor(tu, 'TEST')
    157     assert enum is not None
    158 
    159     assert enum.kind == CursorKind.ENUM_DECL
    160     enum_type = enum.enum_type
    161     assert enum_type.kind == TypeKind.UINT
    162 
    163 def test_enum_type_cpp():
    164     tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp")
    165     enum = get_cursor(tu, 'TEST')
    166     assert enum is not None
    167 
    168     assert enum.kind == CursorKind.ENUM_DECL
    169     assert enum.enum_type.kind == TypeKind.LONGLONG
    170 
    171 def test_objc_type_encoding():
    172     tu = get_tu('int i;', lang='objc')
    173     i = get_cursor(tu, 'i')
    174 
    175     assert i is not None
    176     assert i.objc_type_encoding == 'i'
    177 
    178 def test_enum_values():
    179     tu = get_tu('enum TEST { SPAM=1, EGG, HAM = EGG * 20};')
    180     enum = get_cursor(tu, 'TEST')
    181     assert enum is not None
    182 
    183     assert enum.kind == CursorKind.ENUM_DECL
    184 
    185     enum_constants = list(enum.get_children())
    186     assert len(enum_constants) == 3
    187 
    188     spam, egg, ham = enum_constants
    189 
    190     assert spam.kind == CursorKind.ENUM_CONSTANT_DECL
    191     assert spam.enum_value == 1
    192     assert egg.kind == CursorKind.ENUM_CONSTANT_DECL
    193     assert egg.enum_value == 2
    194     assert ham.kind == CursorKind.ENUM_CONSTANT_DECL
    195     assert ham.enum_value == 40
    196 
    197 def test_enum_values_cpp():
    198     tu = get_tu('enum TEST : long long { SPAM = -1, HAM = 0x10000000000};', lang="cpp")
    199     enum = get_cursor(tu, 'TEST')
    200     assert enum is not None
    201 
    202     assert enum.kind == CursorKind.ENUM_DECL
    203 
    204     enum_constants = list(enum.get_children())
    205     assert len(enum_constants) == 2
    206 
    207     spam, ham = enum_constants
    208 
    209     assert spam.kind == CursorKind.ENUM_CONSTANT_DECL
    210     assert spam.enum_value == -1
    211     assert ham.kind == CursorKind.ENUM_CONSTANT_DECL
    212     assert ham.enum_value == 0x10000000000
    213 
    214 def test_annotation_attribute():
    215     tu = get_tu('int foo (void) __attribute__ ((annotate("here be annotation attribute")));')
    216 
    217     foo = get_cursor(tu, 'foo')
    218     assert foo is not None
    219 
    220     for c in foo.get_children():
    221         if c.kind == CursorKind.ANNOTATE_ATTR:
    222             assert c.displayname == "here be annotation attribute"
    223             break
    224     else:
    225         assert False, "Couldn't find annotation"
    226 
    227 def test_result_type():
    228     tu = get_tu('int foo();')
    229     foo = get_cursor(tu, 'foo')
    230 
    231     assert foo is not None
    232     t = foo.result_type
    233     assert t.kind == TypeKind.INT
    234 
    235 def test_get_tokens():
    236     """Ensure we can map cursors back to tokens."""
    237     tu = get_tu('int foo(int i);')
    238     foo = get_cursor(tu, 'foo')
    239 
    240     tokens = list(foo.get_tokens())
    241     assert len(tokens) == 7
    242     assert tokens[0].spelling == 'int'
    243     assert tokens[1].spelling == 'foo'
    244 
    245 def test_get_arguments():
    246     tu = get_tu('void foo(int i, int j);')
    247     foo = get_cursor(tu, 'foo')
    248     arguments = list(foo.get_arguments())
    249 
    250     assert len(arguments) == 2
    251     assert arguments[0].spelling == "i"
    252     assert arguments[1].spelling == "j"
    253 
    254 def test_referenced():
    255     tu = get_tu('void foo(); void bar() { foo(); }')
    256     foo = get_cursor(tu, 'foo')
    257     bar = get_cursor(tu, 'bar')
    258     for c in bar.get_children():
    259         if c.kind == CursorKind.CALL_EXPR:
    260             assert c.referenced.spelling == foo.spelling
    261             break
    262