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_converting_constructor(): 116 """Ensure Cursor.is_converting_constructor works.""" 117 source = 'class X { explicit X(int); X(double); X(); };' 118 tu = get_tu(source, lang='cpp') 119 120 xs = get_cursors(tu, 'X') 121 122 assert len(xs) == 4 123 assert xs[0].kind == CursorKind.CLASS_DECL 124 cs = xs[1:] 125 assert cs[0].kind == CursorKind.CONSTRUCTOR 126 assert cs[1].kind == CursorKind.CONSTRUCTOR 127 assert cs[2].kind == CursorKind.CONSTRUCTOR 128 129 assert not cs[0].is_converting_constructor() 130 assert cs[1].is_converting_constructor() 131 assert not cs[2].is_converting_constructor() 132 133 134def test_is_copy_constructor(): 135 """Ensure Cursor.is_copy_constructor works.""" 136 source = 'class X { X(); X(const X&); X(X&&); };' 137 tu = get_tu(source, lang='cpp') 138 139 xs = get_cursors(tu, 'X') 140 assert xs[0].kind == CursorKind.CLASS_DECL 141 cs = xs[1:] 142 assert cs[0].kind == CursorKind.CONSTRUCTOR 143 assert cs[1].kind == CursorKind.CONSTRUCTOR 144 assert cs[2].kind == CursorKind.CONSTRUCTOR 145 146 assert not cs[0].is_copy_constructor() 147 assert cs[1].is_copy_constructor() 148 assert not cs[2].is_copy_constructor() 149 150def test_is_default_constructor(): 151 """Ensure Cursor.is_default_constructor works.""" 152 source = 'class X { X(); X(int); };' 153 tu = get_tu(source, lang='cpp') 154 155 xs = get_cursors(tu, 'X') 156 assert xs[0].kind == CursorKind.CLASS_DECL 157 cs = xs[1:] 158 assert cs[0].kind == CursorKind.CONSTRUCTOR 159 assert cs[1].kind == CursorKind.CONSTRUCTOR 160 161 assert cs[0].is_default_constructor() 162 assert not cs[1].is_default_constructor() 163 164def test_is_move_constructor(): 165 """Ensure Cursor.is_move_constructor works.""" 166 source = 'class X { X(); X(const X&); X(X&&); };' 167 tu = get_tu(source, lang='cpp') 168 169 xs = get_cursors(tu, 'X') 170 assert xs[0].kind == CursorKind.CLASS_DECL 171 cs = xs[1:] 172 assert cs[0].kind == CursorKind.CONSTRUCTOR 173 assert cs[1].kind == CursorKind.CONSTRUCTOR 174 assert cs[2].kind == CursorKind.CONSTRUCTOR 175 176 assert not cs[0].is_move_constructor() 177 assert not cs[1].is_move_constructor() 178 assert cs[2].is_move_constructor() 179 180def test_is_default_method(): 181 """Ensure Cursor.is_default_method works.""" 182 source = 'class X { X() = default; }; class Y { Y(); };' 183 tu = get_tu(source, lang='cpp') 184 185 xs = get_cursors(tu, 'X') 186 ys = get_cursors(tu, 'Y') 187 188 assert len(xs) == 2 189 assert len(ys) == 2 190 191 xc = xs[1] 192 yc = ys[1] 193 194 assert xc.is_default_method() 195 assert not yc.is_default_method() 196 197def test_is_mutable_field(): 198 """Ensure Cursor.is_mutable_field works.""" 199 source = 'class X { int x_; mutable int y_; };' 200 tu = get_tu(source, lang='cpp') 201 202 cls = get_cursor(tu, 'X') 203 x_ = get_cursor(tu, 'x_') 204 y_ = get_cursor(tu, 'y_') 205 assert cls is not None 206 assert x_ is not None 207 assert y_ is not None 208 209 assert not x_.is_mutable_field() 210 assert y_.is_mutable_field() 211 212def test_is_static_method(): 213 """Ensure Cursor.is_static_method works.""" 214 215 source = 'class X { static void foo(); void bar(); };' 216 tu = get_tu(source, lang='cpp') 217 218 cls = get_cursor(tu, 'X') 219 foo = get_cursor(tu, 'foo') 220 bar = get_cursor(tu, 'bar') 221 assert cls is not None 222 assert foo is not None 223 assert bar is not None 224 225 assert foo.is_static_method() 226 assert not bar.is_static_method() 227 228def test_is_pure_virtual_method(): 229 """Ensure Cursor.is_pure_virtual_method works.""" 230 source = 'class X { virtual void foo() = 0; virtual void bar(); };' 231 tu = get_tu(source, lang='cpp') 232 233 cls = get_cursor(tu, 'X') 234 foo = get_cursor(tu, 'foo') 235 bar = get_cursor(tu, 'bar') 236 assert cls is not None 237 assert foo is not None 238 assert bar is not None 239 240 assert foo.is_pure_virtual_method() 241 assert not bar.is_pure_virtual_method() 242 243def test_is_virtual_method(): 244 """Ensure Cursor.is_virtual_method works.""" 245 source = 'class X { virtual void foo(); void bar(); };' 246 tu = get_tu(source, lang='cpp') 247 248 cls = get_cursor(tu, 'X') 249 foo = get_cursor(tu, 'foo') 250 bar = get_cursor(tu, 'bar') 251 assert cls is not None 252 assert foo is not None 253 assert bar is not None 254 255 assert foo.is_virtual_method() 256 assert not bar.is_virtual_method() 257 258def test_is_scoped_enum(): 259 """Ensure Cursor.is_scoped_enum works.""" 260 source = 'class X {}; enum RegularEnum {}; enum class ScopedEnum {};' 261 tu = get_tu(source, lang='cpp') 262 263 cls = get_cursor(tu, 'X') 264 regular_enum = get_cursor(tu, 'RegularEnum') 265 scoped_enum = get_cursor(tu, 'ScopedEnum') 266 assert cls is not None 267 assert regular_enum is not None 268 assert scoped_enum is not None 269 270 assert not cls.is_scoped_enum() 271 assert not regular_enum.is_scoped_enum() 272 assert scoped_enum.is_scoped_enum() 273 274def test_underlying_type(): 275 tu = get_tu('typedef int foo;') 276 typedef = get_cursor(tu, 'foo') 277 assert typedef is not None 278 279 assert typedef.kind.is_declaration() 280 underlying = typedef.underlying_typedef_type 281 assert underlying.kind == TypeKind.INT 282 283kParentTest = """\ 284 class C { 285 void f(); 286 } 287 288 void C::f() { } 289 """ 290def test_semantic_parent(): 291 tu = get_tu(kParentTest, 'cpp') 292 curs = get_cursors(tu, 'f') 293 decl = get_cursor(tu, 'C') 294 assert(len(curs) == 2) 295 assert(curs[0].semantic_parent == curs[1].semantic_parent) 296 assert(curs[0].semantic_parent == decl) 297 298def test_lexical_parent(): 299 tu = get_tu(kParentTest, 'cpp') 300 curs = get_cursors(tu, 'f') 301 decl = get_cursor(tu, 'C') 302 assert(len(curs) == 2) 303 assert(curs[0].lexical_parent != curs[1].lexical_parent) 304 assert(curs[0].lexical_parent == decl) 305 assert(curs[1].lexical_parent == tu.cursor) 306 307def test_enum_type(): 308 tu = get_tu('enum TEST { FOO=1, BAR=2 };') 309 enum = get_cursor(tu, 'TEST') 310 assert enum is not None 311 312 assert enum.kind == CursorKind.ENUM_DECL 313 enum_type = enum.enum_type 314 assert enum_type.kind == TypeKind.UINT 315 316def test_enum_type_cpp(): 317 tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp") 318 enum = get_cursor(tu, 'TEST') 319 assert enum is not None 320 321 assert enum.kind == CursorKind.ENUM_DECL 322 assert enum.enum_type.kind == TypeKind.LONGLONG 323 324def test_objc_type_encoding(): 325 tu = get_tu('int i;', lang='objc') 326 i = get_cursor(tu, 'i') 327 328 assert i is not None 329 assert i.objc_type_encoding == 'i' 330 331def test_enum_values(): 332 tu = get_tu('enum TEST { SPAM=1, EGG, HAM = EGG * 20};') 333 enum = get_cursor(tu, 'TEST') 334 assert enum is not None 335 336 assert enum.kind == CursorKind.ENUM_DECL 337 338 enum_constants = list(enum.get_children()) 339 assert len(enum_constants) == 3 340 341 spam, egg, ham = enum_constants 342 343 assert spam.kind == CursorKind.ENUM_CONSTANT_DECL 344 assert spam.enum_value == 1 345 assert egg.kind == CursorKind.ENUM_CONSTANT_DECL 346 assert egg.enum_value == 2 347 assert ham.kind == CursorKind.ENUM_CONSTANT_DECL 348 assert ham.enum_value == 40 349 350def test_enum_values_cpp(): 351 tu = get_tu('enum TEST : long long { SPAM = -1, HAM = 0x10000000000};', lang="cpp") 352 enum = get_cursor(tu, 'TEST') 353 assert enum is not None 354 355 assert enum.kind == CursorKind.ENUM_DECL 356 357 enum_constants = list(enum.get_children()) 358 assert len(enum_constants) == 2 359 360 spam, ham = enum_constants 361 362 assert spam.kind == CursorKind.ENUM_CONSTANT_DECL 363 assert spam.enum_value == -1 364 assert ham.kind == CursorKind.ENUM_CONSTANT_DECL 365 assert ham.enum_value == 0x10000000000 366 367def test_annotation_attribute(): 368 tu = get_tu('int foo (void) __attribute__ ((annotate("here be annotation attribute")));') 369 370 foo = get_cursor(tu, 'foo') 371 assert foo is not None 372 373 for c in foo.get_children(): 374 if c.kind == CursorKind.ANNOTATE_ATTR: 375 assert c.displayname == "here be annotation attribute" 376 break 377 else: 378 assert False, "Couldn't find annotation" 379 380def test_result_type(): 381 tu = get_tu('int foo();') 382 foo = get_cursor(tu, 'foo') 383 384 assert foo is not None 385 t = foo.result_type 386 assert t.kind == TypeKind.INT 387 388def test_get_tokens(): 389 """Ensure we can map cursors back to tokens.""" 390 tu = get_tu('int foo(int i);') 391 foo = get_cursor(tu, 'foo') 392 393 tokens = list(foo.get_tokens()) 394 assert len(tokens) == 6 395 assert tokens[0].spelling == 'int' 396 assert tokens[1].spelling == 'foo' 397 398def test_get_token_cursor(): 399 """Ensure we can map tokens to cursors.""" 400 tu = get_tu('class A {}; int foo(A var = A());', lang='cpp') 401 foo = get_cursor(tu, 'foo') 402 403 for cursor in foo.walk_preorder(): 404 if cursor.kind.is_expression() and not cursor.kind.is_statement(): 405 break 406 else: 407 assert False, "Could not find default value expression" 408 409 tokens = list(cursor.get_tokens()) 410 assert len(tokens) == 4, [t.spelling for t in tokens] 411 assert tokens[0].spelling == '=' 412 assert tokens[1].spelling == 'A' 413 assert tokens[2].spelling == '(' 414 assert tokens[3].spelling == ')' 415 t_cursor = tokens[1].cursor 416 assert t_cursor.kind == CursorKind.TYPE_REF 417 r_cursor = t_cursor.referenced # should not raise an exception 418 assert r_cursor.kind == CursorKind.CLASS_DECL 419 420def test_get_arguments(): 421 tu = get_tu('void foo(int i, int j);') 422 foo = get_cursor(tu, 'foo') 423 arguments = list(foo.get_arguments()) 424 425 assert len(arguments) == 2 426 assert arguments[0].spelling == "i" 427 assert arguments[1].spelling == "j" 428 429kTemplateArgTest = """\ 430 template <int kInt, typename T, bool kBool> 431 void foo(); 432 433 template<> 434 void foo<-7, float, true>(); 435 """ 436 437def test_get_num_template_arguments(): 438 tu = get_tu(kTemplateArgTest, lang='cpp') 439 foos = get_cursors(tu, 'foo') 440 441 assert foos[1].get_num_template_arguments() == 3 442 443def test_get_template_argument_kind(): 444 tu = get_tu(kTemplateArgTest, lang='cpp') 445 foos = get_cursors(tu, 'foo') 446 447 assert foos[1].get_template_argument_kind(0) == TemplateArgumentKind.INTEGRAL 448 assert foos[1].get_template_argument_kind(1) == TemplateArgumentKind.TYPE 449 assert foos[1].get_template_argument_kind(2) == TemplateArgumentKind.INTEGRAL 450 451def test_get_template_argument_type(): 452 tu = get_tu(kTemplateArgTest, lang='cpp') 453 foos = get_cursors(tu, 'foo') 454 455 assert foos[1].get_template_argument_type(1).kind == TypeKind.FLOAT 456 457def test_get_template_argument_value(): 458 tu = get_tu(kTemplateArgTest, lang='cpp') 459 foos = get_cursors(tu, 'foo') 460 461 assert foos[1].get_template_argument_value(0) == -7 462 assert foos[1].get_template_argument_value(2) == True 463 464def test_get_template_argument_unsigned_value(): 465 tu = get_tu(kTemplateArgTest, lang='cpp') 466 foos = get_cursors(tu, 'foo') 467 468 assert foos[1].get_template_argument_unsigned_value(0) == 2 ** 32 - 7 469 assert foos[1].get_template_argument_unsigned_value(2) == True 470 471def test_referenced(): 472 tu = get_tu('void foo(); void bar() { foo(); }') 473 foo = get_cursor(tu, 'foo') 474 bar = get_cursor(tu, 'bar') 475 for c in bar.get_children(): 476 if c.kind == CursorKind.CALL_EXPR: 477 assert c.referenced.spelling == foo.spelling 478 break 479 480def test_mangled_name(): 481 kInputForMangling = """\ 482 int foo(int, int); 483 """ 484 tu = get_tu(kInputForMangling, lang='cpp') 485 foo = get_cursor(tu, 'foo') 486 487 # Since libclang does not link in targets, we cannot pass a triple to it 488 # and force the target. To enable this test to pass on all platforms, accept 489 # all valid manglings. 490 # [c-index-test handles this by running the source through clang, emitting 491 # an AST file and running libclang on that AST file] 492 assert foo.mangled_name in ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH') 493