1import gc 2 3from clang.cindex import CursorKind 4from clang.cindex import TranslationUnit 5from clang.cindex import TypeKind 6from .util import get_cursor 7from .util import get_cursors 8from .util import get_tu 9 10kInput = """\ 11// FIXME: Find nicer way to drop builtins and other cruft. 12int start_decl; 13 14struct s0 { 15 int a; 16 int b; 17}; 18 19struct s1; 20 21void f0(int a0, int a1) { 22 int l0, l1; 23 24 if (a0) 25 return; 26 27 for (;;) { 28 break; 29 } 30} 31""" 32 33def 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 76def 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 93def 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 105def test_underlying_type(): 106 tu = get_tu('typedef int foo;') 107 typedef = get_cursor(tu, 'foo') 108 assert typedef is not None 109 110 assert typedef.kind.is_declaration() 111 underlying = typedef.underlying_typedef_type 112 assert underlying.kind == TypeKind.INT 113 114kParentTest = """\ 115 class C { 116 void f(); 117 } 118 119 void C::f() { } 120 """ 121def test_semantic_parent(): 122 tu = get_tu(kParentTest, 'cpp') 123 curs = get_cursors(tu, 'f') 124 decl = get_cursor(tu, 'C') 125 assert(len(curs) == 2) 126 assert(curs[0].semantic_parent == curs[1].semantic_parent) 127 assert(curs[0].semantic_parent == decl) 128 129def test_lexical_parent(): 130 tu = get_tu(kParentTest, 'cpp') 131 curs = get_cursors(tu, 'f') 132 decl = get_cursor(tu, 'C') 133 assert(len(curs) == 2) 134 assert(curs[0].lexical_parent != curs[1].lexical_parent) 135 assert(curs[0].lexical_parent == decl) 136 assert(curs[1].lexical_parent == tu.cursor) 137 138def test_enum_type(): 139 tu = get_tu('enum TEST { FOO=1, BAR=2 };') 140 enum = get_cursor(tu, 'TEST') 141 assert enum is not None 142 143 assert enum.kind == CursorKind.ENUM_DECL 144 enum_type = enum.enum_type 145 assert enum_type.kind == TypeKind.UINT 146 147def test_enum_type_cpp(): 148 tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp") 149 enum = get_cursor(tu, 'TEST') 150 assert enum is not None 151 152 assert enum.kind == CursorKind.ENUM_DECL 153 assert enum.enum_type.kind == TypeKind.LONGLONG 154 155def test_objc_type_encoding(): 156 tu = get_tu('int i;', lang='objc') 157 i = get_cursor(tu, 'i') 158 159 assert i is not None 160 assert i.objc_type_encoding == 'i' 161 162def test_enum_values(): 163 tu = get_tu('enum TEST { SPAM=1, EGG, HAM = EGG * 20};') 164 enum = get_cursor(tu, 'TEST') 165 assert enum is not None 166 167 assert enum.kind == CursorKind.ENUM_DECL 168 169 enum_constants = list(enum.get_children()) 170 assert len(enum_constants) == 3 171 172 spam, egg, ham = enum_constants 173 174 assert spam.kind == CursorKind.ENUM_CONSTANT_DECL 175 assert spam.enum_value == 1 176 assert egg.kind == CursorKind.ENUM_CONSTANT_DECL 177 assert egg.enum_value == 2 178 assert ham.kind == CursorKind.ENUM_CONSTANT_DECL 179 assert ham.enum_value == 40 180 181def test_enum_values_cpp(): 182 tu = get_tu('enum TEST : long long { SPAM = -1, HAM = 0x10000000000};', lang="cpp") 183 enum = get_cursor(tu, 'TEST') 184 assert enum is not None 185 186 assert enum.kind == CursorKind.ENUM_DECL 187 188 enum_constants = list(enum.get_children()) 189 assert len(enum_constants) == 2 190 191 spam, ham = enum_constants 192 193 assert spam.kind == CursorKind.ENUM_CONSTANT_DECL 194 assert spam.enum_value == -1 195 assert ham.kind == CursorKind.ENUM_CONSTANT_DECL 196 assert ham.enum_value == 0x10000000000 197 198def test_annotation_attribute(): 199 tu = get_tu('int foo (void) __attribute__ ((annotate("here be annotation attribute")));') 200 201 foo = get_cursor(tu, 'foo') 202 assert foo is not None 203 204 for c in foo.get_children(): 205 if c.kind == CursorKind.ANNOTATE_ATTR: 206 assert c.displayname == "here be annotation attribute" 207 break 208 else: 209 assert False, "Couldn't find annotation" 210 211def test_result_type(): 212 tu = get_tu('int foo();') 213 foo = get_cursor(tu, 'foo') 214 215 assert foo is not None 216 t = foo.result_type 217 assert t.kind == TypeKind.INT 218