brintos

brintos / llvm-project-archived public Read only

0
0
Text · 35.0 KiB · 7cb616a Raw
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