1082 lines · python
1import os2 3from clang.cindex import (4 AvailabilityKind,5 BinaryOperator,6 Config,7 Cursor,8 CursorKind,9 PrintingPolicy,10 PrintingPolicyProperty,11 StorageClass,12 TemplateArgumentKind,13 TranslationUnit,14 TypeKind,15 conf,16)17 18if "CLANG_LIBRARY_PATH" in os.environ:19 Config.set_library_path(os.environ["CLANG_LIBRARY_PATH"])20 21import gc22import unittest23 24from .util import get_cursor, get_cursors, get_tu25 26CHILDREN_TEST = """\27struct s0 {28 int a;29 int b;30};31 32struct s1;33 34void f0(int a0, int a1) {35 int l0, l1;36 37 if (a0)38 return;39 40 for (;;) {41 break;42 }43}44"""45 46PARENT_TEST = """\47 class C {48 void f();49 }50 51 void C::f() { }52 """53 54TEMPLATE_ARG_TEST = """\55 template <int kInt, typename T, bool kBool>56 void foo();57 58 template<>59 void foo<-7, float, true>();60 """61 62BINOPS = """\63struct C {64 int m;65 };66 67 void func(void){68 int a, b;69 int C::* p = &C::70 71 C c;72 c.*p;73 74 C* pc;75 pc->*p;76 77 a * b;78 a / b;79 a % b;80 a + b;81 a - b;82 83 a << b;84 a >> b;85 86 a < b;87 a > b;88 89 a <= b;90 a >= b;91 a == b;92 a != b;93 94 a & b;95 a ^ b;96 a | b;97 98 a && b;99 a || b;100 101 a = b;102 103 a *= b;104 a /= b;105 a %= b;106 a += b;107 a -= b;108 109 a <<= b;110 a >>= b;111 112 a &= b;113 a ^= b;114 a |= b;115 a , b;116 117 }118 """119 120 121class TestCursor(unittest.TestCase):122 def test_get_children(self):123 tu = get_tu(CHILDREN_TEST)124 125 it = tu.cursor.get_children()126 tu_nodes = list(it)127 128 self.assertEqual(len(tu_nodes), 3)129 for cursor in tu_nodes:130 self.assertIsNotNone(cursor.translation_unit)131 132 self.assertNotEqual(tu_nodes[0], tu_nodes[1])133 self.assertEqual(tu_nodes[0].kind, CursorKind.STRUCT_DECL)134 self.assertEqual(tu_nodes[0].spelling, "s0")135 self.assertEqual(tu_nodes[0].is_definition(), True)136 self.assertEqual(tu_nodes[0].location.file.name, "t.c")137 self.assertEqual(tu_nodes[0].location.line, 1)138 self.assertEqual(tu_nodes[0].location.column, 8)139 self.assertGreater(tu_nodes[0].hash, 0)140 self.assertIsNotNone(tu_nodes[0].translation_unit)141 142 s0_nodes = list(tu_nodes[0].get_children())143 self.assertEqual(len(s0_nodes), 2)144 self.assertEqual(s0_nodes[0].kind, CursorKind.FIELD_DECL)145 self.assertEqual(s0_nodes[0].spelling, "a")146 self.assertEqual(s0_nodes[0].type.kind, TypeKind.INT)147 self.assertEqual(s0_nodes[1].kind, CursorKind.FIELD_DECL)148 self.assertEqual(s0_nodes[1].spelling, "b")149 self.assertEqual(s0_nodes[1].type.kind, TypeKind.INT)150 151 self.assertEqual(tu_nodes[1].kind, CursorKind.STRUCT_DECL)152 self.assertEqual(tu_nodes[1].spelling, "s1")153 self.assertEqual(tu_nodes[1].displayname, "s1")154 self.assertEqual(tu_nodes[1].is_definition(), False)155 156 self.assertEqual(tu_nodes[2].kind, CursorKind.FUNCTION_DECL)157 self.assertEqual(tu_nodes[2].spelling, "f0")158 self.assertEqual(tu_nodes[2].displayname, "f0(int, int)")159 self.assertEqual(tu_nodes[2].is_definition(), True)160 161 def test_references(self):162 """Ensure that references to TranslationUnit are kept."""163 tu = get_tu("int x;")164 cursors = list(tu.cursor.get_children())165 self.assertGreater(len(cursors), 0)166 167 cursor = cursors[0]168 self.assertIsInstance(cursor.translation_unit, TranslationUnit)169 170 # Delete reference to TU and perform a full GC.171 del tu172 gc.collect()173 self.assertIsInstance(cursor.translation_unit, TranslationUnit)174 175 # If the TU was destroyed, this should cause a segfault.176 cursor.semantic_parent177 178 def test_canonical(self):179 source = "struct X; struct X; struct X { int member; };"180 tu = get_tu(source)181 182 cursors = []183 for cursor in tu.cursor.get_children():184 if cursor.spelling == "X":185 cursors.append(cursor)186 187 self.assertEqual(len(cursors), 3)188 self.assertEqual(cursors[1].canonical, cursors[2].canonical)189 190 def test_is_const_method(self):191 """Ensure Cursor.is_const_method works."""192 source = "class X { void foo() const; void bar(); };"193 tu = get_tu(source, lang="cpp")194 195 cls = get_cursor(tu, "X")196 foo = get_cursor(tu, "foo")197 bar = get_cursor(tu, "bar")198 self.assertIsNotNone(cls)199 self.assertIsNotNone(foo)200 self.assertIsNotNone(bar)201 202 self.assertTrue(foo.is_const_method())203 self.assertFalse(bar.is_const_method())204 205 def test_is_converting_constructor(self):206 """Ensure Cursor.is_converting_constructor works."""207 source = "class X { explicit X(int); X(double); X(); };"208 tu = get_tu(source, lang="cpp")209 210 xs = get_cursors(tu, "X")211 212 self.assertEqual(len(xs), 4)213 self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL)214 cs = xs[1:]215 self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR)216 self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR)217 self.assertEqual(cs[2].kind, CursorKind.CONSTRUCTOR)218 219 self.assertFalse(cs[0].is_converting_constructor())220 self.assertTrue(cs[1].is_converting_constructor())221 self.assertFalse(cs[2].is_converting_constructor())222 223 def test_is_copy_constructor(self):224 """Ensure Cursor.is_copy_constructor works."""225 source = "class X { X(); X(const X&); X(X&&); };"226 tu = get_tu(source, lang="cpp")227 228 xs = get_cursors(tu, "X")229 self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL)230 cs = xs[1:]231 self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR)232 self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR)233 self.assertEqual(cs[2].kind, CursorKind.CONSTRUCTOR)234 235 self.assertFalse(cs[0].is_copy_constructor())236 self.assertTrue(cs[1].is_copy_constructor())237 self.assertFalse(cs[2].is_copy_constructor())238 239 def test_is_default_constructor(self):240 """Ensure Cursor.is_default_constructor works."""241 source = "class X { X(); X(int); };"242 tu = get_tu(source, lang="cpp")243 244 xs = get_cursors(tu, "X")245 self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL)246 cs = xs[1:]247 self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR)248 self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR)249 250 self.assertTrue(cs[0].is_default_constructor())251 self.assertFalse(cs[1].is_default_constructor())252 253 def test_is_move_constructor(self):254 """Ensure Cursor.is_move_constructor works."""255 source = "class X { X(); X(const X&); X(X&&); };"256 tu = get_tu(source, lang="cpp")257 258 xs = get_cursors(tu, "X")259 self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL)260 cs = xs[1:]261 self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR)262 self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR)263 self.assertEqual(cs[2].kind, CursorKind.CONSTRUCTOR)264 265 self.assertFalse(cs[0].is_move_constructor())266 self.assertFalse(cs[1].is_move_constructor())267 self.assertTrue(cs[2].is_move_constructor())268 269 def test_is_default_method(self):270 """Ensure Cursor.is_default_method works."""271 source = "class X { X() = default; }; class Y { Y(); };"272 tu = get_tu(source, lang="cpp")273 274 xs = get_cursors(tu, "X")275 ys = get_cursors(tu, "Y")276 277 self.assertEqual(len(xs), 2)278 self.assertEqual(len(ys), 2)279 280 xc = xs[1]281 yc = ys[1]282 283 self.assertTrue(xc.is_default_method())284 self.assertFalse(yc.is_default_method())285 286 def test_is_deleted_method(self):287 source = "class X { X() = delete; }; class Y { Y(); };"288 tu = get_tu(source, lang="cpp")289 290 xs = get_cursors(tu, "X")291 ys = get_cursors(tu, "Y")292 293 self.assertEqual(len(xs), 2)294 self.assertEqual(len(ys), 2)295 296 xc = xs[1]297 yc = ys[1]298 299 self.assertTrue(xc.is_deleted_method())300 self.assertFalse(yc.is_deleted_method())301 302 def test_is_copy_assignment_operator_method(self):303 source_with_copy_assignment_operators = """304 struct Foo {305 // Those are copy-assignment operators306 bool operator=(const Foo&);307 bool operator=(Foo&);308 Foo operator=(Foo);309 bool operator=(volatile Foo&);310 bool operator=(const volatile Foo&);311 312 // Positive-check that the recognition works for templated classes too313 template <typename T>314 class Bar {315 bool operator=(const Bar&);316 Bar operator=(const Bar);317 bool operator=(Bar<T>&);318 bool operator=(volatile Bar&);319 bool operator=(const volatile Bar<T>&);320 };321 """322 source_without_copy_assignment_operators = """323 struct Foo {324 // Those are not copy-assignment operators325 template<typename T>326 bool operator=(const T&);327 bool operator=(const bool&);328 bool operator=(char&);329 bool operator=(volatile unsigned int&);330 bool operator=(const volatile unsigned char&);331 bool operator=(int);332 bool operator=(Foo&&);333 };334 """335 tu_with_copy_assignment_operators = get_tu(336 source_with_copy_assignment_operators, lang="cpp"337 )338 tu_without_copy_assignment_operators = get_tu(339 source_without_copy_assignment_operators, lang="cpp"340 )341 342 copy_assignment_operators_cursors = get_cursors(343 tu_with_copy_assignment_operators, "operator="344 )345 non_copy_assignment_operators_cursors = get_cursors(346 tu_without_copy_assignment_operators, "operator="347 )348 349 self.assertEqual(len(copy_assignment_operators_cursors), 10)350 self.assertEqual(len(non_copy_assignment_operators_cursors), 7)351 352 self.assertTrue(353 all(354 [355 cursor.is_copy_assignment_operator_method()356 for cursor in copy_assignment_operators_cursors357 ]358 )359 )360 361 self.assertFalse(362 any(363 [364 cursor.is_copy_assignment_operator_method()365 for cursor in non_copy_assignment_operators_cursors366 ]367 )368 )369 370 def test_is_move_assignment_operator_method(self):371 """Ensure Cursor.is_move_assignment_operator_method works."""372 source_with_move_assignment_operators = """373 struct Foo {374 // Those are move-assignment operators375 bool operator=(const Foo&&);376 bool operator=(Foo&&);377 bool operator=(volatile Foo&&);378 bool operator=(const volatile Foo&&);379 380 // Positive-check that the recognition works for templated classes too381 template <typename T>382 class Bar {383 bool operator=(const Bar&&);384 bool operator=(Bar<T>&&);385 bool operator=(volatile Bar&&);386 bool operator=(const volatile Bar<T>&&);387 };388 """389 source_without_move_assignment_operators = """390 struct Foo {391 // Those are not move-assignment operators392 template<typename T>393 bool operator=(const T&&);394 bool operator=(const bool&&);395 bool operator=(char&&);396 bool operator=(volatile unsigned int&&);397 bool operator=(const volatile unsigned char&&);398 bool operator=(int);399 bool operator=(Foo);400 };401 """402 tu_with_move_assignment_operators = get_tu(403 source_with_move_assignment_operators, lang="cpp"404 )405 tu_without_move_assignment_operators = get_tu(406 source_without_move_assignment_operators, lang="cpp"407 )408 409 move_assignment_operators_cursors = get_cursors(410 tu_with_move_assignment_operators, "operator="411 )412 non_move_assignment_operators_cursors = get_cursors(413 tu_without_move_assignment_operators, "operator="414 )415 416 self.assertEqual(len(move_assignment_operators_cursors), 8)417 self.assertTrue(len(non_move_assignment_operators_cursors), 7)418 419 self.assertTrue(420 all(421 [422 cursor.is_move_assignment_operator_method()423 for cursor in move_assignment_operators_cursors424 ]425 )426 )427 self.assertFalse(428 any(429 [430 cursor.is_move_assignment_operator_method()431 for cursor in non_move_assignment_operators_cursors432 ]433 )434 )435 436 def test_is_explicit_method(self):437 """Ensure Cursor.is_explicit_method works."""438 source_with_explicit_methods = """439 struct Foo {440 // Those are explicit441 explicit Foo(double);442 explicit(true) Foo(char);443 explicit operator double();444 explicit(true) operator char();445 };446 """447 source_without_explicit_methods = """448 struct Foo {449 // Those are not explicit450 Foo(int);451 explicit(false) Foo(float);452 operator int();453 explicit(false) operator float();454 };455 """456 tu_with_explicit_methods = get_tu(source_with_explicit_methods, lang="cpp")457 tu_without_explicit_methods = get_tu(458 source_without_explicit_methods, lang="cpp"459 )460 461 explicit_methods_cursors = [462 *get_cursors(tu_with_explicit_methods, "Foo")[1:],463 get_cursor(tu_with_explicit_methods, "operator double"),464 get_cursor(tu_with_explicit_methods, "operator char"),465 ]466 467 non_explicit_methods_cursors = [468 *get_cursors(tu_without_explicit_methods, "Foo")[1:],469 get_cursor(tu_without_explicit_methods, "operator int"),470 get_cursor(tu_without_explicit_methods, "operator float"),471 ]472 473 self.assertEqual(len(explicit_methods_cursors), 4)474 self.assertTrue(len(non_explicit_methods_cursors), 4)475 476 self.assertTrue(477 all([cursor.is_explicit_method() for cursor in explicit_methods_cursors])478 )479 self.assertFalse(480 any(481 [cursor.is_explicit_method() for cursor in non_explicit_methods_cursors]482 )483 )484 485 def test_is_mutable_field(self):486 """Ensure Cursor.is_mutable_field works."""487 source = "class X { int x_; mutable int y_; };"488 tu = get_tu(source, lang="cpp")489 490 cls = get_cursor(tu, "X")491 x_ = get_cursor(tu, "x_")492 y_ = get_cursor(tu, "y_")493 self.assertIsNotNone(cls)494 self.assertIsNotNone(x_)495 self.assertIsNotNone(y_)496 497 self.assertFalse(x_.is_mutable_field())498 self.assertTrue(y_.is_mutable_field())499 500 def test_is_static_method(self):501 """Ensure Cursor.is_static_method works."""502 503 source = "class X { static void foo(); void bar(); };"504 tu = get_tu(source, lang="cpp")505 506 cls = get_cursor(tu, "X")507 foo = get_cursor(tu, "foo")508 bar = get_cursor(tu, "bar")509 self.assertIsNotNone(cls)510 self.assertIsNotNone(foo)511 self.assertIsNotNone(bar)512 513 self.assertTrue(foo.is_static_method())514 self.assertFalse(bar.is_static_method())515 516 def test_is_pure_virtual_method(self):517 """Ensure Cursor.is_pure_virtual_method works."""518 source = "class X { virtual void foo() = 0; virtual void bar(); };"519 tu = get_tu(source, lang="cpp")520 521 cls = get_cursor(tu, "X")522 foo = get_cursor(tu, "foo")523 bar = get_cursor(tu, "bar")524 self.assertIsNotNone(cls)525 self.assertIsNotNone(foo)526 self.assertIsNotNone(bar)527 528 self.assertTrue(foo.is_pure_virtual_method())529 self.assertFalse(bar.is_pure_virtual_method())530 531 def test_is_virtual_method(self):532 """Ensure Cursor.is_virtual_method works."""533 source = "class X { virtual void foo(); void bar(); };"534 tu = get_tu(source, lang="cpp")535 536 cls = get_cursor(tu, "X")537 foo = get_cursor(tu, "foo")538 bar = get_cursor(tu, "bar")539 self.assertIsNotNone(cls)540 self.assertIsNotNone(foo)541 self.assertIsNotNone(bar)542 543 self.assertTrue(foo.is_virtual_method())544 self.assertFalse(bar.is_virtual_method())545 546 def test_is_abstract_record(self):547 """Ensure Cursor.is_abstract_record works."""548 source = "struct X { virtual void x() = 0; }; struct Y : X { void x(); };"549 tu = get_tu(source, lang="cpp")550 551 cls = get_cursor(tu, "X")552 self.assertTrue(cls.is_abstract_record())553 554 cls = get_cursor(tu, "Y")555 self.assertFalse(cls.is_abstract_record())556 557 def test_is_scoped_enum(self):558 """Ensure Cursor.is_scoped_enum works."""559 source = "class X {}; enum RegularEnum {}; enum class ScopedEnum {};"560 tu = get_tu(source, lang="cpp")561 562 cls = get_cursor(tu, "X")563 regular_enum = get_cursor(tu, "RegularEnum")564 scoped_enum = get_cursor(tu, "ScopedEnum")565 self.assertIsNotNone(cls)566 self.assertIsNotNone(regular_enum)567 self.assertIsNotNone(scoped_enum)568 569 self.assertFalse(cls.is_scoped_enum())570 self.assertFalse(regular_enum.is_scoped_enum())571 self.assertTrue(scoped_enum.is_scoped_enum())572 573 def test_get_definition(self):574 """Ensure Cursor.get_definition works."""575 tu = get_tu(576 """577class A {578 constexpr static int f(){return 3;}579};580struct B {581 int b = A::f();582};583""",584 lang="cpp",585 )586 curs = get_cursors(tu, "f")587 self.assertEqual(len(curs), 4)588 self.assertEqual(curs[0].kind, CursorKind.CXX_METHOD)589 self.assertEqual(curs[1].get_definition(), curs[0])590 self.assertEqual(curs[2].get_definition(), curs[0])591 self.assertEqual(curs[3].get_definition(), curs[0])592 593 def test_get_usr(self):594 """Ensure Cursor.get_usr works."""595 tu = get_tu(596 """597int add(int, int);598int add(int a, int b) { return a + b; }599int add(float a, float b) { return a + b; }600""",601 lang="cpp",602 )603 curs = get_cursors(tu, "add")604 self.assertEqual(len(curs), 3)605 self.assertEqual(curs[0].get_usr(), curs[1].get_usr())606 self.assertNotEqual(curs[0].get_usr(), curs[2].get_usr())607 608 def test_underlying_type(self):609 tu = get_tu("typedef int foo;")610 typedef = get_cursor(tu, "foo")611 self.assertIsNotNone(typedef)612 613 self.assertTrue(typedef.kind.is_declaration())614 underlying = typedef.underlying_typedef_type615 self.assertEqual(underlying.kind, TypeKind.INT)616 617 def test_semantic_parent(self):618 tu = get_tu(PARENT_TEST, "cpp")619 curs = get_cursors(tu, "f")620 decl = get_cursor(tu, "C")621 self.assertEqual(len(curs), 2)622 self.assertEqual(curs[0].semantic_parent, curs[1].semantic_parent)623 self.assertEqual(curs[0].semantic_parent, decl)624 625 def test_lexical_parent(self):626 tu = get_tu(PARENT_TEST, "cpp")627 curs = get_cursors(tu, "f")628 decl = get_cursor(tu, "C")629 self.assertEqual(len(curs), 2)630 self.assertNotEqual(curs[0].lexical_parent, curs[1].lexical_parent)631 self.assertEqual(curs[0].lexical_parent, decl)632 self.assertEqual(curs[1].lexical_parent, tu.cursor)633 634 def test_enum_type(self):635 tu = get_tu("enum TEST { FOO=1, BAR=2 };")636 enum = get_cursor(tu, "TEST")637 self.assertIsNotNone(enum)638 639 self.assertEqual(enum.kind, CursorKind.ENUM_DECL)640 enum_type = enum.enum_type641 self.assertIn(enum_type.kind, (TypeKind.UINT, TypeKind.INT))642 643 def test_enum_type_cpp(self):644 tu = get_tu("enum TEST : long long { FOO=1, BAR=2 };", lang="cpp")645 enum = get_cursor(tu, "TEST")646 self.assertIsNotNone(enum)647 648 self.assertEqual(enum.kind, CursorKind.ENUM_DECL)649 self.assertEqual(enum.enum_type.kind, TypeKind.LONGLONG)650 651 def test_objc_type_encoding(self):652 tu = get_tu("int i;", lang="objc")653 i = get_cursor(tu, "i")654 655 self.assertIsNotNone(i)656 self.assertEqual(i.objc_type_encoding, "i")657 658 def test_enum_values(self):659 tu = get_tu("enum TEST { SPAM=1, EGG, HAM = EGG * 20};")660 enum = get_cursor(tu, "TEST")661 self.assertIsNotNone(enum)662 663 self.assertEqual(enum.kind, CursorKind.ENUM_DECL)664 665 enum_constants = list(enum.get_children())666 self.assertEqual(len(enum_constants), 3)667 668 spam, egg, ham = enum_constants669 670 self.assertEqual(spam.kind, CursorKind.ENUM_CONSTANT_DECL)671 self.assertEqual(spam.enum_value, 1)672 self.assertEqual(egg.kind, CursorKind.ENUM_CONSTANT_DECL)673 self.assertEqual(egg.enum_value, 2)674 self.assertEqual(ham.kind, CursorKind.ENUM_CONSTANT_DECL)675 self.assertEqual(ham.enum_value, 40)676 677 def test_enum_values_cpp(self):678 tu = get_tu(679 "enum TEST : long long { SPAM = -1, HAM = 0x10000000000};", lang="cpp"680 )681 enum = get_cursor(tu, "TEST")682 self.assertIsNotNone(enum)683 684 self.assertEqual(enum.kind, CursorKind.ENUM_DECL)685 686 enum_constants = list(enum.get_children())687 self.assertEqual(len(enum_constants), 2)688 689 spam, ham = enum_constants690 691 self.assertEqual(spam.kind, CursorKind.ENUM_CONSTANT_DECL)692 self.assertEqual(spam.enum_value, -1)693 self.assertEqual(ham.kind, CursorKind.ENUM_CONSTANT_DECL)694 self.assertEqual(ham.enum_value, 0x10000000000)695 696 def test_enum_values_unsigned(self):697 tu = get_tu("enum TEST : unsigned char { SPAM=0, HAM = 200};", lang="cpp")698 enum = get_cursor(tu, "TEST")699 self.assertIsNotNone(enum)700 701 self.assertEqual(enum.kind, CursorKind.ENUM_DECL)702 703 enum_constants = list(enum.get_children())704 self.assertEqual(len(enum_constants), 2)705 706 spam, ham = enum_constants707 708 self.assertEqual(spam.kind, CursorKind.ENUM_CONSTANT_DECL)709 self.assertEqual(spam.enum_value, 0)710 self.assertEqual(ham.kind, CursorKind.ENUM_CONSTANT_DECL)711 self.assertEqual(ham.enum_value, 200)712 713 def test_annotation_attribute(self):714 tu = get_tu(715 'int foo (void) __attribute__ ((annotate("here be annotation attribute")));'716 )717 718 foo = get_cursor(tu, "foo")719 self.assertIsNotNone(foo)720 721 for c in foo.get_children():722 if c.kind == CursorKind.ANNOTATE_ATTR:723 self.assertEqual(c.displayname, "here be annotation attribute")724 break725 else:726 self.fail("Couldn't find annotation")727 728 def test_annotation_template(self):729 annotation = '__attribute__ ((annotate("annotation")))'730 for source, kind in [731 ("int foo (T value) %s;", CursorKind.FUNCTION_TEMPLATE),732 ("class %s foo {};", CursorKind.CLASS_TEMPLATE),733 ]:734 source = "template<typename T> " + (source % annotation)735 tu = get_tu(source, lang="cpp")736 737 foo = get_cursor(tu, "foo")738 self.assertIsNotNone(foo)739 self.assertEqual(foo.kind, kind)740 741 for c in foo.get_children():742 if c.kind == CursorKind.ANNOTATE_ATTR:743 self.assertEqual(c.displayname, "annotation")744 break745 else:746 self.fail("Couldn't find annotation for {}".format(kind))747 748 def test_result_type(self):749 tu = get_tu("int foo();")750 foo = get_cursor(tu, "foo")751 752 self.assertIsNotNone(foo)753 t = foo.result_type754 self.assertEqual(t.kind, TypeKind.INT)755 756 def test_result_type_objc_method_decl(self):757 code = """\758 @interface Interface : NSObject759 -(void)voidMethod;760 @end761 """762 tu = get_tu(code, lang="objc")763 cursor = get_cursor(tu, "voidMethod")764 result_type = cursor.result_type765 self.assertEqual(cursor.kind, CursorKind.OBJC_INSTANCE_METHOD_DECL)766 self.assertEqual(result_type.kind, TypeKind.VOID)767 768 def test_storage_class(self):769 tu = get_tu(770 """771extern int ex;772register int reg;773int count(int a, int b){774 static int counter = 0;775 return 0;776}777""",778 lang="cpp",779 )780 cursor = get_cursor(tu, "ex")781 self.assertEqual(cursor.storage_class, StorageClass.EXTERN)782 cursor = get_cursor(tu, "counter")783 self.assertEqual(cursor.storage_class, StorageClass.STATIC)784 cursor = get_cursor(tu, "reg")785 self.assertEqual(cursor.storage_class, StorageClass.REGISTER)786 787 def test_function_inlined(self):788 tu = get_tu(789 """790inline void f_inline(void);791void f_noninline(void);792int d_noninline;793"""794 )795 cursor = get_cursor(tu, "f_inline")796 self.assertEqual(cursor.is_function_inlined(), True)797 cursor = get_cursor(tu, "f_noninline")798 self.assertEqual(cursor.is_function_inlined(), False)799 cursor = get_cursor(tu, "d_noninline")800 self.assertEqual(cursor.is_function_inlined(), False)801 802 def test_availability(self):803 tu = get_tu("class A { A(A const&) = delete; };", lang="cpp")804 805 # AvailabilityKind.AVAILABLE806 cursor = get_cursor(tu, "A")807 self.assertEqual(cursor.kind, CursorKind.CLASS_DECL)808 self.assertEqual(cursor.availability, AvailabilityKind.AVAILABLE)809 810 # AvailabilityKind.NOT_AVAILABLE811 cursors = get_cursors(tu, "A")812 for c in cursors:813 if c.kind == CursorKind.CONSTRUCTOR:814 self.assertEqual(c.availability, AvailabilityKind.NOT_AVAILABLE)815 break816 else:817 self.fail("Could not find cursor for deleted constructor")818 819 # AvailabilityKind.DEPRECATED820 tu = get_tu("void test() __attribute__((deprecated));", lang="cpp")821 cursor = get_cursor(tu, "test")822 self.assertEqual(cursor.availability, AvailabilityKind.DEPRECATED)823 824 # AvailabilityKind.NOT_ACCESSIBLE is only used in the code completion results825 826 def test_get_tokens(self):827 """Ensure we can map cursors back to tokens."""828 tu = get_tu("int foo(int i);")829 foo = get_cursor(tu, "foo")830 831 tokens = list(foo.get_tokens())832 self.assertEqual(len(tokens), 6)833 self.assertEqual(tokens[0].spelling, "int")834 self.assertEqual(tokens[1].spelling, "foo")835 836 def test_get_token_cursor(self):837 """Ensure we can map tokens to cursors."""838 tu = get_tu("class A {}; int foo(A var = A());", lang="cpp")839 foo = get_cursor(tu, "foo")840 841 for cursor in foo.walk_preorder():842 if cursor.kind.is_expression() and not cursor.kind.is_statement():843 break844 else:845 self.fail("Could not find default value expression")846 847 tokens = list(cursor.get_tokens())848 self.assertEqual(len(tokens), 4, [t.spelling for t in tokens])849 self.assertEqual(tokens[0].spelling, "=")850 self.assertEqual(tokens[1].spelling, "A")851 self.assertEqual(tokens[2].spelling, "(")852 self.assertEqual(tokens[3].spelling, ")")853 t_cursor = tokens[1].cursor854 self.assertEqual(t_cursor.kind, CursorKind.TYPE_REF)855 r_cursor = t_cursor.referenced # should not raise an exception856 self.assertEqual(r_cursor.kind, CursorKind.CLASS_DECL)857 858 def test_get_field_offsetof(self):859 tu = get_tu(860 "struct myStruct {int a; char b; char c; short d; char e;};", lang="cpp"861 )862 c1 = get_cursor(tu, "myStruct")863 c2 = get_cursor(tu, "a")864 c3 = get_cursor(tu, "b")865 c4 = get_cursor(tu, "c")866 c5 = get_cursor(tu, "d")867 c6 = get_cursor(tu, "e")868 self.assertEqual(c1.get_field_offsetof(), -1)869 self.assertEqual(c2.get_field_offsetof(), 0)870 self.assertEqual(c3.get_field_offsetof(), 32)871 self.assertEqual(c4.get_field_offsetof(), 40)872 self.assertEqual(c5.get_field_offsetof(), 48)873 self.assertEqual(c6.get_field_offsetof(), 64)874 875 def test_get_arguments(self):876 tu = get_tu("void foo(int i, int j);")877 foo = get_cursor(tu, "foo")878 arguments = list(foo.get_arguments())879 880 self.assertEqual(len(arguments), 2)881 self.assertEqual(arguments[0].spelling, "i")882 self.assertEqual(arguments[1].spelling, "j")883 884 def test_get_num_template_arguments(self):885 tu = get_tu(TEMPLATE_ARG_TEST, lang="cpp")886 foos = get_cursors(tu, "foo")887 888 self.assertEqual(foos[1].get_num_template_arguments(), 3)889 890 def test_get_template_argument_kind(self):891 tu = get_tu(TEMPLATE_ARG_TEST, lang="cpp")892 foos = get_cursors(tu, "foo")893 894 self.assertEqual(895 foos[1].get_template_argument_kind(0), TemplateArgumentKind.INTEGRAL896 )897 self.assertEqual(898 foos[1].get_template_argument_kind(1), TemplateArgumentKind.TYPE899 )900 self.assertEqual(901 foos[1].get_template_argument_kind(2), TemplateArgumentKind.INTEGRAL902 )903 904 def test_get_template_argument_type(self):905 tu = get_tu(TEMPLATE_ARG_TEST, lang="cpp")906 foos = get_cursors(tu, "foo")907 908 self.assertEqual(foos[1].get_template_argument_type(1).kind, TypeKind.FLOAT)909 910 def test_get_template_argument_value(self):911 tu = get_tu(TEMPLATE_ARG_TEST, lang="cpp")912 foos = get_cursors(tu, "foo")913 914 self.assertEqual(foos[1].get_template_argument_value(0), -7)915 self.assertEqual(foos[1].get_template_argument_value(2), True)916 917 def test_get_template_argument_unsigned_value(self):918 tu = get_tu(TEMPLATE_ARG_TEST, lang="cpp")919 foos = get_cursors(tu, "foo")920 921 self.assertEqual(foos[1].get_template_argument_unsigned_value(0), 2**32 - 7)922 self.assertEqual(foos[1].get_template_argument_unsigned_value(2), True)923 924 def test_referenced(self):925 tu = get_tu("void foo(); void bar() { foo(); }")926 foo = get_cursor(tu, "foo")927 bar = get_cursor(tu, "bar")928 for c in bar.get_children():929 if c.kind == CursorKind.CALL_EXPR:930 self.assertEqual(c.referenced.spelling, foo.spelling)931 break932 933 def test_mangled_name(self):934 kInputForMangling = """\935 int foo(int, int);936 """937 tu = get_tu(kInputForMangling, lang="cpp")938 foo = get_cursor(tu, "foo")939 940 # Since libclang does not link in targets, we cannot pass a triple to it941 # and force the target. To enable this test to pass on all platforms, accept942 # all valid manglings.943 # [c-index-test handles this by running the source through clang, emitting944 # an AST file and running libclang on that AST file]945 self.assertIn(946 foo.mangled_name, ("_Z3fooii", "__Z3fooii", "?foo@@YAHHH", "?foo@@YAHHH@Z")947 )948 949 def test_binop(self):950 tu = get_tu(BINOPS, lang="cpp")951 952 operators = {953 # not exposed yet954 # ".*" : BinaryOperator.PtrMemD,955 "->*": BinaryOperator.PtrMemI,956 "*": BinaryOperator.Mul,957 "/": BinaryOperator.Div,958 "%": BinaryOperator.Rem,959 "+": BinaryOperator.Add,960 "-": BinaryOperator.Sub,961 "<<": BinaryOperator.Shl,962 ">>": BinaryOperator.Shr,963 # tests do not run in C++2a mode so this operator is not available964 # "<=>" : BinaryOperator.Cmp,965 "<": BinaryOperator.LT,966 ">": BinaryOperator.GT,967 "<=": BinaryOperator.LE,968 ">=": BinaryOperator.GE,969 "==": BinaryOperator.EQ,970 "!=": BinaryOperator.NE,971 "&": BinaryOperator.And,972 "^": BinaryOperator.Xor,973 "|": BinaryOperator.Or,974 "&&": BinaryOperator.LAnd,975 "||": BinaryOperator.LOr,976 "=": BinaryOperator.Assign,977 "*=": BinaryOperator.MulAssign,978 "/=": BinaryOperator.DivAssign,979 "%=": BinaryOperator.RemAssign,980 "+=": BinaryOperator.AddAssign,981 "-=": BinaryOperator.SubAssign,982 "<<=": BinaryOperator.ShlAssign,983 ">>=": BinaryOperator.ShrAssign,984 "&=": BinaryOperator.AndAssign,985 "^=": BinaryOperator.XorAssign,986 "|=": BinaryOperator.OrAssign,987 ",": BinaryOperator.Comma,988 }989 990 for op, typ in operators.items():991 c = get_cursor(tu, op)992 assert c.binary_operator == typ993 994 def test_from_result_null(self):995 tu = get_tu("int a = 1+2;", lang="cpp")996 op = next(next(tu.cursor.get_children()).get_children())997 self.assertEqual(op.kind, CursorKind.BINARY_OPERATOR)998 self.assertEqual(op.get_definition(), None)999 1000 def test_from_cursor_result_null(self):1001 tu = get_tu("")1002 self.assertEqual(tu.cursor.semantic_parent, None)1003 1004 def test_pretty_print(self):1005 tu = get_tu("struct X { int x; }; void f(bool x) { }", lang="cpp")1006 f = get_cursor(tu, "f")1007 1008 self.assertEqual(f.displayname, "f(bool)")1009 pp = PrintingPolicy.create(f)1010 self.assertEqual(pp.get_property(PrintingPolicyProperty.Bool), True)1011 self.assertEqual(f.pretty_printed(pp), "void f(bool x) {\n}\n")1012 pp.set_property(PrintingPolicyProperty.Bool, False)1013 self.assertEqual(pp.get_property(PrintingPolicyProperty.Bool), False)1014 self.assertEqual(f.pretty_printed(pp), "void f(_Bool x) {\n}\n")1015 1016 def test_hash(self):1017 def accumulate_cursors(cursor: Cursor, all_cursors: list):1018 all_cursors.append(cursor)1019 for child in cursor.get_children():1020 all_cursors = accumulate_cursors(child, all_cursors)1021 return all_cursors1022 1023 tu = get_tu(CHILDREN_TEST)1024 all_cursors = accumulate_cursors(tu.cursor, [])1025 cursor_hashes = set()1026 for cursor in all_cursors:1027 self.assertNotIn(hash(cursor), cursor_hashes)1028 cursor_hashes.add(hash(cursor))1029 1030 def test_has_attrs(self):1031 tu = get_tu(1032 """1033struct A;1034struct A final {};1035 1036struct B;1037struct B {};1038""",1039 lang="cpp",1040 )1041 A = get_cursor(tu, "A")1042 B = get_cursor(tu, "B")1043 self.assertTrue(A.get_definition().has_attrs())1044 self.assertFalse(B.get_definition().has_attrs())1045 1046 def test_specialized_template(self):1047 tu = get_tu(TEMPLATE_ARG_TEST, lang="cpp")1048 foos = get_cursors(tu, "foo")1049 prime_foo = foos[1].specialized_template1050 1051 self.assertNotEqual(foos[0], foos[1])1052 self.assertEqual(foos[0], prime_foo)1053 self.assertIsNone(tu.cursor.specialized_template)1054 1055 def test_equality(self):1056 tu = get_tu(CHILDREN_TEST, lang="cpp")1057 cursor1 = get_cursor(tu, "s0")1058 cursor1_2 = get_cursor(tu, "s0")1059 cursor2 = get_cursor(tu, "f0")1060 1061 self.assertIsNotNone(cursor1)1062 self.assertIsNotNone(cursor1_2)1063 self.assertIsNotNone(cursor2)1064 1065 self.assertEqual(cursor1, cursor1)1066 self.assertEqual(cursor1, cursor1_2)1067 self.assertNotEqual(cursor1, cursor2)1068 self.assertNotEqual(cursor1, "foo")1069 1070 def test_null_cursor(self):1071 tu = get_tu("int a = 729;")1072 1073 for cursor in tu.cursor.walk_preorder():1074 self.assertFalse(cursor.is_null())1075 1076 nc = conf.lib.clang_getNullCursor()1077 self.assertTrue(nc.is_null())1078 with self.assertRaises(Exception):1079 nc.is_definition()1080 with self.assertRaises(Exception):1081 nc.spelling1082