1import ctypes 2import gc 3 4from clang.cindex import CursorKind 5from clang.cindex import TemplateArgumentKind 6from clang.cindex import TranslationUnit 7from clang.cindex import TypeKind 8from .util import get_cursor 9from .util import get_cursors 10from .util import get_tu 11 12kInput = """\ 13struct s0 { 14 int a; 15 int b; 16}; 17 18struct s1; 19 20void f0(int a0, int a1) { 21 int l0, l1; 22 23 if (a0) 24 return; 25 26 for (;;) { 27 break; 28 } 29} 30""" 31 32def test_get_children(): 33 tu = get_tu(kInput) 34 35 it = tu.cursor.get_children() 36 tu_nodes = list(it) 37 38 assert len(tu_nodes) == 3 39 for cursor in tu_nodes: 40 assert cursor.translation_unit is not None 41 42 assert tu_nodes[0] != tu_nodes[1] 43 assert tu_nodes[0].kind == CursorKind.STRUCT_DECL 44 assert tu_nodes[0].spelling == 's0' 45 assert tu_nodes[0].is_definition() == True 46 assert tu_nodes[0].location.file.name == 't.c' 47 assert tu_nodes[0].location.line == 1 48 assert tu_nodes[0].location.column == 8 49 assert tu_nodes[0].hash > 0 50 assert tu_nodes[0].translation_unit is not None 51 52 s0_nodes = list(tu_nodes[0].get_children()) 53 assert len(s0_nodes) == 2 54 assert s0_nodes[0].kind == CursorKind.FIELD_DECL 55 assert s0_nodes[0].spelling == 'a' 56 assert s0_nodes[0].type.kind == TypeKind.INT 57 assert s0_nodes[1].kind == CursorKind.FIELD_DECL 58 assert s0_nodes[1].spelling == 'b' 59 assert s0_nodes[1].type.kind == TypeKind.INT 60 61 assert tu_nodes[1].kind == CursorKind.STRUCT_DECL 62 assert tu_nodes[1].spelling == 's1' 63 assert tu_nodes[1].displayname == 's1' 64 assert tu_nodes[1].is_definition() == False 65 66 assert tu_nodes[2].kind == CursorKind.FUNCTION_DECL 67 assert tu_nodes[2].spelling == 'f0' 68 assert tu_nodes[2].displayname == 'f0(int, int)' 69 assert tu_nodes[2].is_definition() == True 70 71def test_references(): 72 """Ensure that references to TranslationUnit are kept.""" 73 tu = get_tu('int x;') 74 cursors = list(tu.cursor.get_children()) 75 assert len(cursors) > 0 76 77 cursor = cursors[0] 78 assert isinstance(cursor.translation_unit, TranslationUnit) 79 80 # Delete reference to TU and perform a full GC. 81 del tu 82 gc.collect() 83 assert isinstance(cursor.translation_unit, TranslationUnit) 84 85 # If the TU was destroyed, this should cause a segfault. 86 parent = cursor.semantic_parent 87 88def test_canonical(): 89 source = 'struct X; struct X; struct X { int member; };' 90 tu = get_tu(source) 91 92 cursors = [] 93 for cursor in tu.cursor.get_children(): 94 if cursor.spelling == 'X': 95 cursors.append(cursor) 96 97 assert len(cursors) == 3 98 assert cursors[1].canonical == cursors[2].canonical 99 100def test_is_const_method(): 101 """Ensure Cursor.is_const_method works.""" 102 source = 'class X { void foo() const; void bar(); };' 103 tu = get_tu(source, lang='cpp') 104 105 cls = get_cursor(tu, 'X') 106 foo = get_cursor(tu, 'foo') 107 bar = get_cursor(tu, 'bar') 108 assert cls is not None 109 assert foo is not None 110 assert bar is not None 111 112 assert foo.is_const_method() 113 assert not bar.is_const_method() 114 115def test_is_mutable_field(): 116 """Ensure Cursor.is_mutable_field works.""" 117 source = 'class X { int x_; mutable int y_; };' 118 tu = get_tu(source, lang='cpp') 119 120 cls = get_cursor(tu, 'X') 121 x_ = get_cursor(tu, 'x_') 122 y_ = get_cursor(tu, 'y_') 123 assert cls is not None 124 assert x_ is not None 125 assert y_ is not None 126 127 assert not x_.is_mutable_field() 128 assert y_.is_mutable_field() 129 130def test_is_static_method(): 131 """Ensure Cursor.is_static_method works.""" 132 133 source = 'class X { static void foo(); void bar(); };' 134 tu = get_tu(source, lang='cpp') 135 136 cls = get_cursor(tu, 'X') 137 foo = get_cursor(tu, 'foo') 138 bar = get_cursor(tu, 'bar') 139 assert cls is not None 140 assert foo is not None 141 assert bar is not None 142 143 assert foo.is_static_method() 144 assert not bar.is_static_method() 145 146def test_is_pure_virtual_method(): 147 """Ensure Cursor.is_pure_virtual_method works.""" 148 source = 'class X { virtual void foo() = 0; virtual void bar(); };' 149 tu = get_tu(source, lang='cpp') 150 151 cls = get_cursor(tu, 'X') 152 foo = get_cursor(tu, 'foo') 153 bar = get_cursor(tu, 'bar') 154 assert cls is not None 155 assert foo is not None 156 assert bar is not None 157 158 assert foo.is_pure_virtual_method() 159 assert not bar.is_pure_virtual_method() 160 161def test_is_virtual_method(): 162 """Ensure Cursor.is_virtual_method works.""" 163 source = 'class X { virtual void foo(); void bar(); };' 164 tu = get_tu(source, lang='cpp') 165 166 cls = get_cursor(tu, 'X') 167 foo = get_cursor(tu, 'foo') 168 bar = get_cursor(tu, 'bar') 169 assert cls is not None 170 assert foo is not None 171 assert bar is not None 172 173 assert foo.is_virtual_method() 174 assert not bar.is_virtual_method() 175 176def test_underlying_type(): 177 tu = get_tu('typedef int foo;') 178 typedef = get_cursor(tu, 'foo') 179 assert typedef is not None 180 181 assert typedef.kind.is_declaration() 182 underlying = typedef.underlying_typedef_type 183 assert underlying.kind == TypeKind.INT 184 185kParentTest = """\ 186 class C { 187 void f(); 188 } 189 190 void C::f() { } 191 """ 192def test_semantic_parent(): 193 tu = get_tu(kParentTest, 'cpp') 194 curs = get_cursors(tu, 'f') 195 decl = get_cursor(tu, 'C') 196 assert(len(curs) == 2) 197 assert(curs[0].semantic_parent == curs[1].semantic_parent) 198 assert(curs[0].semantic_parent == decl) 199 200def test_lexical_parent(): 201 tu = get_tu(kParentTest, 'cpp') 202 curs = get_cursors(tu, 'f') 203 decl = get_cursor(tu, 'C') 204 assert(len(curs) == 2) 205 assert(curs[0].lexical_parent != curs[1].lexical_parent) 206 assert(curs[0].lexical_parent == decl) 207 assert(curs[1].lexical_parent == tu.cursor) 208 209def test_enum_type(): 210 tu = get_tu('enum TEST { FOO=1, BAR=2 };') 211 enum = get_cursor(tu, 'TEST') 212 assert enum is not None 213 214 assert enum.kind == CursorKind.ENUM_DECL 215 enum_type = enum.enum_type 216 assert enum_type.kind == TypeKind.UINT 217 218def test_enum_type_cpp(): 219 tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp") 220 enum = get_cursor(tu, 'TEST') 221 assert enum is not None 222 223 assert enum.kind == CursorKind.ENUM_DECL 224 assert enum.enum_type.kind == TypeKind.LONGLONG 225 226def test_objc_type_encoding(): 227 tu = get_tu('int i;', lang='objc') 228 i = get_cursor(tu, 'i') 229 230 assert i is not None 231 assert i.objc_type_encoding == 'i' 232 233def test_enum_values(): 234 tu = get_tu('enum TEST { SPAM=1, EGG, HAM = EGG * 20};') 235 enum = get_cursor(tu, 'TEST') 236 assert enum is not None 237 238 assert enum.kind == CursorKind.ENUM_DECL 239 240 enum_constants = list(enum.get_children()) 241 assert len(enum_constants) == 3 242 243 spam, egg, ham = enum_constants 244 245 assert spam.kind == CursorKind.ENUM_CONSTANT_DECL 246 assert spam.enum_value == 1 247 assert egg.kind == CursorKind.ENUM_CONSTANT_DECL 248 assert egg.enum_value == 2 249 assert ham.kind == CursorKind.ENUM_CONSTANT_DECL 250 assert ham.enum_value == 40 251 252def test_enum_values_cpp(): 253 tu = get_tu('enum TEST : long long { SPAM = -1, HAM = 0x10000000000};', lang="cpp") 254 enum = get_cursor(tu, 'TEST') 255 assert enum is not None 256 257 assert enum.kind == CursorKind.ENUM_DECL 258 259 enum_constants = list(enum.get_children()) 260 assert len(enum_constants) == 2 261 262 spam, ham = enum_constants 263 264 assert spam.kind == CursorKind.ENUM_CONSTANT_DECL 265 assert spam.enum_value == -1 266 assert ham.kind == CursorKind.ENUM_CONSTANT_DECL 267 assert ham.enum_value == 0x10000000000 268 269def test_annotation_attribute(): 270 tu = get_tu('int foo (void) __attribute__ ((annotate("here be annotation attribute")));') 271 272 foo = get_cursor(tu, 'foo') 273 assert foo is not None 274 275 for c in foo.get_children(): 276 if c.kind == CursorKind.ANNOTATE_ATTR: 277 assert c.displayname == "here be annotation attribute" 278 break 279 else: 280 assert False, "Couldn't find annotation" 281 282def test_result_type(): 283 tu = get_tu('int foo();') 284 foo = get_cursor(tu, 'foo') 285 286 assert foo is not None 287 t = foo.result_type 288 assert t.kind == TypeKind.INT 289 290def test_get_tokens(): 291 """Ensure we can map cursors back to tokens.""" 292 tu = get_tu('int foo(int i);') 293 foo = get_cursor(tu, 'foo') 294 295 tokens = list(foo.get_tokens()) 296 assert len(tokens) == 7 297 assert tokens[0].spelling == 'int' 298 assert tokens[1].spelling == 'foo' 299 300def test_get_arguments(): 301 tu = get_tu('void foo(int i, int j);') 302 foo = get_cursor(tu, 'foo') 303 arguments = list(foo.get_arguments()) 304 305 assert len(arguments) == 2 306 assert arguments[0].spelling == "i" 307 assert arguments[1].spelling == "j" 308 309kTemplateArgTest = """\ 310 template <int kInt, typename T, bool kBool> 311 void foo(); 312 313 template<> 314 void foo<-7, float, true>(); 315 """ 316 317def test_get_num_template_arguments(): 318 tu = get_tu(kTemplateArgTest, lang='cpp') 319 foos = get_cursors(tu, 'foo') 320 321 assert foos[1].get_num_template_arguments() == 3 322 323def test_get_template_argument_kind(): 324 tu = get_tu(kTemplateArgTest, lang='cpp') 325 foos = get_cursors(tu, 'foo') 326 327 assert foos[1].get_template_argument_kind(0) == TemplateArgumentKind.INTEGRAL 328 assert foos[1].get_template_argument_kind(1) == TemplateArgumentKind.TYPE 329 assert foos[1].get_template_argument_kind(2) == TemplateArgumentKind.INTEGRAL 330 331def test_get_template_argument_type(): 332 tu = get_tu(kTemplateArgTest, lang='cpp') 333 foos = get_cursors(tu, 'foo') 334 335 assert foos[1].get_template_argument_type(1).kind == TypeKind.FLOAT 336 337def test_get_template_argument_value(): 338 tu = get_tu(kTemplateArgTest, lang='cpp') 339 foos = get_cursors(tu, 'foo') 340 341 assert foos[1].get_template_argument_value(0) == -7 342 assert foos[1].get_template_argument_value(2) == True 343 344def test_get_template_argument_unsigned_value(): 345 tu = get_tu(kTemplateArgTest, lang='cpp') 346 foos = get_cursors(tu, 'foo') 347 348 assert foos[1].get_template_argument_unsigned_value(0) == 2 ** 32 - 7 349 assert foos[1].get_template_argument_unsigned_value(2) == True 350 351def test_referenced(): 352 tu = get_tu('void foo(); void bar() { foo(); }') 353 foo = get_cursor(tu, 'foo') 354 bar = get_cursor(tu, 'bar') 355 for c in bar.get_children(): 356 if c.kind == CursorKind.CALL_EXPR: 357 assert c.referenced.spelling == foo.spelling 358 break 359 360def test_mangled_name(): 361 kInputForMangling = """\ 362 int foo(int, int); 363 """ 364 tu = get_tu(kInputForMangling, lang='cpp') 365 foo = get_cursor(tu, 'foo') 366 367 # Since libclang does not link in targets, we cannot pass a triple to it 368 # and force the target. To enable this test to pass on all platforms, accept 369 # all valid manglings. 370 # [c-index-test handles this by running the source through clang, emitting 371 # an AST file and running libclang on that AST file] 372 assert foo.mangled_name in ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH') 373