xref: /openbsd-src/gnu/llvm/clang/bindings/python/tests/cindex/test_cursor.py (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrickimport os
2e5dd7070Spatrickfrom clang.cindex import Config
3e5dd7070Spatrickif 'CLANG_LIBRARY_PATH' in os.environ:
4e5dd7070Spatrick    Config.set_library_path(os.environ['CLANG_LIBRARY_PATH'])
5e5dd7070Spatrick
6e5dd7070Spatrickimport ctypes
7e5dd7070Spatrickimport gc
8e5dd7070Spatrickimport unittest
9e5dd7070Spatrick
10e5dd7070Spatrickfrom clang.cindex import AvailabilityKind
11e5dd7070Spatrickfrom clang.cindex import CursorKind
12e5dd7070Spatrickfrom clang.cindex import TemplateArgumentKind
13e5dd7070Spatrickfrom clang.cindex import TranslationUnit
14e5dd7070Spatrickfrom clang.cindex import TypeKind
15e5dd7070Spatrickfrom .util import get_cursor
16e5dd7070Spatrickfrom .util import get_cursors
17e5dd7070Spatrickfrom .util import get_tu
18e5dd7070Spatrick
19e5dd7070Spatrick
20e5dd7070SpatrickkInput = """\
21e5dd7070Spatrickstruct s0 {
22e5dd7070Spatrick  int a;
23e5dd7070Spatrick  int b;
24e5dd7070Spatrick};
25e5dd7070Spatrick
26e5dd7070Spatrickstruct s1;
27e5dd7070Spatrick
28e5dd7070Spatrickvoid f0(int a0, int a1) {
29e5dd7070Spatrick  int l0, l1;
30e5dd7070Spatrick
31e5dd7070Spatrick  if (a0)
32e5dd7070Spatrick    return;
33e5dd7070Spatrick
34e5dd7070Spatrick  for (;;) {
35e5dd7070Spatrick    break;
36e5dd7070Spatrick  }
37e5dd7070Spatrick}
38e5dd7070Spatrick"""
39e5dd7070Spatrick
40e5dd7070SpatrickkParentTest = """\
41e5dd7070Spatrick        class C {
42e5dd7070Spatrick            void f();
43e5dd7070Spatrick        }
44e5dd7070Spatrick
45e5dd7070Spatrick        void C::f() { }
46e5dd7070Spatrick    """
47e5dd7070Spatrick
48e5dd7070SpatrickkTemplateArgTest = """\
49e5dd7070Spatrick        template <int kInt, typename T, bool kBool>
50e5dd7070Spatrick        void foo();
51e5dd7070Spatrick
52e5dd7070Spatrick        template<>
53e5dd7070Spatrick        void foo<-7, float, true>();
54e5dd7070Spatrick    """
55e5dd7070Spatrick
56e5dd7070Spatrickclass TestCursor(unittest.TestCase):
57e5dd7070Spatrick    def test_get_children(self):
58e5dd7070Spatrick        tu = get_tu(kInput)
59e5dd7070Spatrick
60e5dd7070Spatrick        it = tu.cursor.get_children()
61e5dd7070Spatrick        tu_nodes = list(it)
62e5dd7070Spatrick
63e5dd7070Spatrick        self.assertEqual(len(tu_nodes), 3)
64e5dd7070Spatrick        for cursor in tu_nodes:
65e5dd7070Spatrick            self.assertIsNotNone(cursor.translation_unit)
66e5dd7070Spatrick
67e5dd7070Spatrick        self.assertNotEqual(tu_nodes[0], tu_nodes[1])
68e5dd7070Spatrick        self.assertEqual(tu_nodes[0].kind, CursorKind.STRUCT_DECL)
69e5dd7070Spatrick        self.assertEqual(tu_nodes[0].spelling, 's0')
70e5dd7070Spatrick        self.assertEqual(tu_nodes[0].is_definition(), True)
71e5dd7070Spatrick        self.assertEqual(tu_nodes[0].location.file.name, 't.c')
72e5dd7070Spatrick        self.assertEqual(tu_nodes[0].location.line, 1)
73e5dd7070Spatrick        self.assertEqual(tu_nodes[0].location.column, 8)
74e5dd7070Spatrick        self.assertGreater(tu_nodes[0].hash, 0)
75e5dd7070Spatrick        self.assertIsNotNone(tu_nodes[0].translation_unit)
76e5dd7070Spatrick
77e5dd7070Spatrick        s0_nodes = list(tu_nodes[0].get_children())
78e5dd7070Spatrick        self.assertEqual(len(s0_nodes), 2)
79e5dd7070Spatrick        self.assertEqual(s0_nodes[0].kind, CursorKind.FIELD_DECL)
80e5dd7070Spatrick        self.assertEqual(s0_nodes[0].spelling, 'a')
81e5dd7070Spatrick        self.assertEqual(s0_nodes[0].type.kind, TypeKind.INT)
82e5dd7070Spatrick        self.assertEqual(s0_nodes[1].kind, CursorKind.FIELD_DECL)
83e5dd7070Spatrick        self.assertEqual(s0_nodes[1].spelling, 'b')
84e5dd7070Spatrick        self.assertEqual(s0_nodes[1].type.kind, TypeKind.INT)
85e5dd7070Spatrick
86e5dd7070Spatrick        self.assertEqual(tu_nodes[1].kind, CursorKind.STRUCT_DECL)
87e5dd7070Spatrick        self.assertEqual(tu_nodes[1].spelling, 's1')
88e5dd7070Spatrick        self.assertEqual(tu_nodes[1].displayname, 's1')
89e5dd7070Spatrick        self.assertEqual(tu_nodes[1].is_definition(), False)
90e5dd7070Spatrick
91e5dd7070Spatrick        self.assertEqual(tu_nodes[2].kind, CursorKind.FUNCTION_DECL)
92e5dd7070Spatrick        self.assertEqual(tu_nodes[2].spelling, 'f0')
93e5dd7070Spatrick        self.assertEqual(tu_nodes[2].displayname, 'f0(int, int)')
94e5dd7070Spatrick        self.assertEqual(tu_nodes[2].is_definition(), True)
95e5dd7070Spatrick
96e5dd7070Spatrick    def test_references(self):
97e5dd7070Spatrick        """Ensure that references to TranslationUnit are kept."""
98e5dd7070Spatrick        tu = get_tu('int x;')
99e5dd7070Spatrick        cursors = list(tu.cursor.get_children())
100e5dd7070Spatrick        self.assertGreater(len(cursors), 0)
101e5dd7070Spatrick
102e5dd7070Spatrick        cursor = cursors[0]
103e5dd7070Spatrick        self.assertIsInstance(cursor.translation_unit, TranslationUnit)
104e5dd7070Spatrick
105e5dd7070Spatrick        # Delete reference to TU and perform a full GC.
106e5dd7070Spatrick        del tu
107e5dd7070Spatrick        gc.collect()
108e5dd7070Spatrick        self.assertIsInstance(cursor.translation_unit, TranslationUnit)
109e5dd7070Spatrick
110e5dd7070Spatrick        # If the TU was destroyed, this should cause a segfault.
111e5dd7070Spatrick        parent = cursor.semantic_parent
112e5dd7070Spatrick
113e5dd7070Spatrick    def test_canonical(self):
114e5dd7070Spatrick        source = 'struct X; struct X; struct X { int member; };'
115e5dd7070Spatrick        tu = get_tu(source)
116e5dd7070Spatrick
117e5dd7070Spatrick        cursors = []
118e5dd7070Spatrick        for cursor in tu.cursor.get_children():
119e5dd7070Spatrick            if cursor.spelling == 'X':
120e5dd7070Spatrick                cursors.append(cursor)
121e5dd7070Spatrick
122e5dd7070Spatrick        self.assertEqual(len(cursors), 3)
123e5dd7070Spatrick        self.assertEqual(cursors[1].canonical, cursors[2].canonical)
124e5dd7070Spatrick
125e5dd7070Spatrick    def test_is_const_method(self):
126e5dd7070Spatrick        """Ensure Cursor.is_const_method works."""
127e5dd7070Spatrick        source = 'class X { void foo() const; void bar(); };'
128e5dd7070Spatrick        tu = get_tu(source, lang='cpp')
129e5dd7070Spatrick
130e5dd7070Spatrick        cls = get_cursor(tu, 'X')
131e5dd7070Spatrick        foo = get_cursor(tu, 'foo')
132e5dd7070Spatrick        bar = get_cursor(tu, 'bar')
133e5dd7070Spatrick        self.assertIsNotNone(cls)
134e5dd7070Spatrick        self.assertIsNotNone(foo)
135e5dd7070Spatrick        self.assertIsNotNone(bar)
136e5dd7070Spatrick
137e5dd7070Spatrick        self.assertTrue(foo.is_const_method())
138e5dd7070Spatrick        self.assertFalse(bar.is_const_method())
139e5dd7070Spatrick
140e5dd7070Spatrick    def test_is_converting_constructor(self):
141e5dd7070Spatrick        """Ensure Cursor.is_converting_constructor works."""
142e5dd7070Spatrick        source = 'class X { explicit X(int); X(double); X(); };'
143e5dd7070Spatrick        tu = get_tu(source, lang='cpp')
144e5dd7070Spatrick
145e5dd7070Spatrick        xs = get_cursors(tu, 'X')
146e5dd7070Spatrick
147e5dd7070Spatrick        self.assertEqual(len(xs), 4)
148e5dd7070Spatrick        self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL)
149e5dd7070Spatrick        cs = xs[1:]
150e5dd7070Spatrick        self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR)
151e5dd7070Spatrick        self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR)
152e5dd7070Spatrick        self.assertEqual(cs[2].kind, CursorKind.CONSTRUCTOR)
153e5dd7070Spatrick
154e5dd7070Spatrick        self.assertFalse(cs[0].is_converting_constructor())
155e5dd7070Spatrick        self.assertTrue(cs[1].is_converting_constructor())
156e5dd7070Spatrick        self.assertFalse(cs[2].is_converting_constructor())
157e5dd7070Spatrick
158e5dd7070Spatrick
159e5dd7070Spatrick    def test_is_copy_constructor(self):
160e5dd7070Spatrick        """Ensure Cursor.is_copy_constructor works."""
161e5dd7070Spatrick        source = 'class X { X(); X(const X&); X(X&&); };'
162e5dd7070Spatrick        tu = get_tu(source, lang='cpp')
163e5dd7070Spatrick
164e5dd7070Spatrick        xs = get_cursors(tu, 'X')
165e5dd7070Spatrick        self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL)
166e5dd7070Spatrick        cs = xs[1:]
167e5dd7070Spatrick        self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR)
168e5dd7070Spatrick        self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR)
169e5dd7070Spatrick        self.assertEqual(cs[2].kind, CursorKind.CONSTRUCTOR)
170e5dd7070Spatrick
171e5dd7070Spatrick        self.assertFalse(cs[0].is_copy_constructor())
172e5dd7070Spatrick        self.assertTrue(cs[1].is_copy_constructor())
173e5dd7070Spatrick        self.assertFalse(cs[2].is_copy_constructor())
174e5dd7070Spatrick
175e5dd7070Spatrick    def test_is_default_constructor(self):
176e5dd7070Spatrick        """Ensure Cursor.is_default_constructor works."""
177e5dd7070Spatrick        source = 'class X { X(); X(int); };'
178e5dd7070Spatrick        tu = get_tu(source, lang='cpp')
179e5dd7070Spatrick
180e5dd7070Spatrick        xs = get_cursors(tu, 'X')
181e5dd7070Spatrick        self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL)
182e5dd7070Spatrick        cs = xs[1:]
183e5dd7070Spatrick        self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR)
184e5dd7070Spatrick        self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR)
185e5dd7070Spatrick
186e5dd7070Spatrick        self.assertTrue(cs[0].is_default_constructor())
187e5dd7070Spatrick        self.assertFalse(cs[1].is_default_constructor())
188e5dd7070Spatrick
189e5dd7070Spatrick    def test_is_move_constructor(self):
190e5dd7070Spatrick        """Ensure Cursor.is_move_constructor works."""
191e5dd7070Spatrick        source = 'class X { X(); X(const X&); X(X&&); };'
192e5dd7070Spatrick        tu = get_tu(source, lang='cpp')
193e5dd7070Spatrick
194e5dd7070Spatrick        xs = get_cursors(tu, 'X')
195e5dd7070Spatrick        self.assertEqual(xs[0].kind, CursorKind.CLASS_DECL)
196e5dd7070Spatrick        cs = xs[1:]
197e5dd7070Spatrick        self.assertEqual(cs[0].kind, CursorKind.CONSTRUCTOR)
198e5dd7070Spatrick        self.assertEqual(cs[1].kind, CursorKind.CONSTRUCTOR)
199e5dd7070Spatrick        self.assertEqual(cs[2].kind, CursorKind.CONSTRUCTOR)
200e5dd7070Spatrick
201e5dd7070Spatrick        self.assertFalse(cs[0].is_move_constructor())
202e5dd7070Spatrick        self.assertFalse(cs[1].is_move_constructor())
203e5dd7070Spatrick        self.assertTrue(cs[2].is_move_constructor())
204e5dd7070Spatrick
205e5dd7070Spatrick    def test_is_default_method(self):
206e5dd7070Spatrick        """Ensure Cursor.is_default_method works."""
207e5dd7070Spatrick        source = 'class X { X() = default; }; class Y { Y(); };'
208e5dd7070Spatrick        tu = get_tu(source, lang='cpp')
209e5dd7070Spatrick
210e5dd7070Spatrick        xs = get_cursors(tu, 'X')
211e5dd7070Spatrick        ys = get_cursors(tu, 'Y')
212e5dd7070Spatrick
213e5dd7070Spatrick        self.assertEqual(len(xs), 2)
214e5dd7070Spatrick        self.assertEqual(len(ys), 2)
215e5dd7070Spatrick
216e5dd7070Spatrick        xc = xs[1]
217e5dd7070Spatrick        yc = ys[1]
218e5dd7070Spatrick
219e5dd7070Spatrick        self.assertTrue(xc.is_default_method())
220e5dd7070Spatrick        self.assertFalse(yc.is_default_method())
221e5dd7070Spatrick
222*12c85518Srobert    def test_is_move_assignment_operator_method(self):
223*12c85518Srobert        """Ensure Cursor.is_move_assignment_operator_method works."""
224*12c85518Srobert        source_with_move_assignment_operators = """
225*12c85518Srobert        struct Foo {
226*12c85518Srobert           // Those are move-assignment operators
227*12c85518Srobert           bool operator=(const Foo&&);
228*12c85518Srobert           bool operator=(Foo&&);
229*12c85518Srobert           bool operator=(volatile Foo&&);
230*12c85518Srobert           bool operator=(const volatile Foo&&);
231*12c85518Srobert
232*12c85518Srobert        // Positive-check that the recognition works for templated classes too
233*12c85518Srobert        template <typename T>
234*12c85518Srobert        class Bar {
235*12c85518Srobert            bool operator=(const Bar&&);
236*12c85518Srobert            bool operator=(Bar<T>&&);
237*12c85518Srobert            bool operator=(volatile Bar&&);
238*12c85518Srobert            bool operator=(const volatile Bar<T>&&);
239*12c85518Srobert        };
240*12c85518Srobert        """
241*12c85518Srobert        source_without_move_assignment_operators = """
242*12c85518Srobert        struct Foo {
243*12c85518Srobert            // Those are not move-assignment operators
244*12c85518Srobert            template<typename T>
245*12c85518Srobert            bool operator=(const T&&);
246*12c85518Srobert            bool operator=(const bool&&);
247*12c85518Srobert            bool operator=(char&&);
248*12c85518Srobert            bool operator=(volatile unsigned int&&);
249*12c85518Srobert            bool operator=(const volatile unsigned char&&);
250*12c85518Srobert            bool operator=(int);
251*12c85518Srobert            bool operator=(Foo);
252*12c85518Srobert        };
253*12c85518Srobert        """
254*12c85518Srobert        tu_with_move_assignment_operators = get_tu(
255*12c85518Srobert            source_with_move_assignment_operators, lang="cpp"
256*12c85518Srobert        )
257*12c85518Srobert        tu_without_move_assignment_operators = get_tu(
258*12c85518Srobert            source_without_move_assignment_operators, lang="cpp"
259*12c85518Srobert        )
260*12c85518Srobert
261*12c85518Srobert        move_assignment_operators_cursors = get_cursors(
262*12c85518Srobert            tu_with_move_assignment_operators, "operator="
263*12c85518Srobert        )
264*12c85518Srobert        non_move_assignment_operators_cursors = get_cursors(
265*12c85518Srobert            tu_without_move_assignment_operators, "operator="
266*12c85518Srobert        )
267*12c85518Srobert
268*12c85518Srobert        self.assertEqual(len(move_assignment_operators_cursors), 8)
269*12c85518Srobert        self.assertTrue(len(non_move_assignment_operators_cursors), 7)
270*12c85518Srobert
271*12c85518Srobert        self.assertTrue(all([
272*12c85518Srobert            cursor.is_move_assignment_operator_method()
273*12c85518Srobert            for cursor in move_assignment_operators_cursors
274*12c85518Srobert        ]))
275*12c85518Srobert        self.assertFalse(any([
276*12c85518Srobert            cursor.is_move_assignment_operator_method()
277*12c85518Srobert            for cursor in non_move_assignment_operators_cursors
278*12c85518Srobert        ]))
279*12c85518Srobert
280e5dd7070Spatrick    def test_is_mutable_field(self):
281e5dd7070Spatrick        """Ensure Cursor.is_mutable_field works."""
282e5dd7070Spatrick        source = 'class X { int x_; mutable int y_; };'
283e5dd7070Spatrick        tu = get_tu(source, lang='cpp')
284e5dd7070Spatrick
285e5dd7070Spatrick        cls = get_cursor(tu, 'X')
286e5dd7070Spatrick        x_ = get_cursor(tu, 'x_')
287e5dd7070Spatrick        y_ = get_cursor(tu, 'y_')
288e5dd7070Spatrick        self.assertIsNotNone(cls)
289e5dd7070Spatrick        self.assertIsNotNone(x_)
290e5dd7070Spatrick        self.assertIsNotNone(y_)
291e5dd7070Spatrick
292e5dd7070Spatrick        self.assertFalse(x_.is_mutable_field())
293e5dd7070Spatrick        self.assertTrue(y_.is_mutable_field())
294e5dd7070Spatrick
295e5dd7070Spatrick    def test_is_static_method(self):
296e5dd7070Spatrick        """Ensure Cursor.is_static_method works."""
297e5dd7070Spatrick
298e5dd7070Spatrick        source = 'class X { static void foo(); void bar(); };'
299e5dd7070Spatrick        tu = get_tu(source, lang='cpp')
300e5dd7070Spatrick
301e5dd7070Spatrick        cls = get_cursor(tu, 'X')
302e5dd7070Spatrick        foo = get_cursor(tu, 'foo')
303e5dd7070Spatrick        bar = get_cursor(tu, 'bar')
304e5dd7070Spatrick        self.assertIsNotNone(cls)
305e5dd7070Spatrick        self.assertIsNotNone(foo)
306e5dd7070Spatrick        self.assertIsNotNone(bar)
307e5dd7070Spatrick
308e5dd7070Spatrick        self.assertTrue(foo.is_static_method())
309e5dd7070Spatrick        self.assertFalse(bar.is_static_method())
310e5dd7070Spatrick
311e5dd7070Spatrick    def test_is_pure_virtual_method(self):
312e5dd7070Spatrick        """Ensure Cursor.is_pure_virtual_method works."""
313e5dd7070Spatrick        source = 'class X { virtual void foo() = 0; virtual void bar(); };'
314e5dd7070Spatrick        tu = get_tu(source, lang='cpp')
315e5dd7070Spatrick
316e5dd7070Spatrick        cls = get_cursor(tu, 'X')
317e5dd7070Spatrick        foo = get_cursor(tu, 'foo')
318e5dd7070Spatrick        bar = get_cursor(tu, 'bar')
319e5dd7070Spatrick        self.assertIsNotNone(cls)
320e5dd7070Spatrick        self.assertIsNotNone(foo)
321e5dd7070Spatrick        self.assertIsNotNone(bar)
322e5dd7070Spatrick
323e5dd7070Spatrick        self.assertTrue(foo.is_pure_virtual_method())
324e5dd7070Spatrick        self.assertFalse(bar.is_pure_virtual_method())
325e5dd7070Spatrick
326e5dd7070Spatrick    def test_is_virtual_method(self):
327e5dd7070Spatrick        """Ensure Cursor.is_virtual_method works."""
328e5dd7070Spatrick        source = 'class X { virtual void foo(); void bar(); };'
329e5dd7070Spatrick        tu = get_tu(source, lang='cpp')
330e5dd7070Spatrick
331e5dd7070Spatrick        cls = get_cursor(tu, 'X')
332e5dd7070Spatrick        foo = get_cursor(tu, 'foo')
333e5dd7070Spatrick        bar = get_cursor(tu, 'bar')
334e5dd7070Spatrick        self.assertIsNotNone(cls)
335e5dd7070Spatrick        self.assertIsNotNone(foo)
336e5dd7070Spatrick        self.assertIsNotNone(bar)
337e5dd7070Spatrick
338e5dd7070Spatrick        self.assertTrue(foo.is_virtual_method())
339e5dd7070Spatrick        self.assertFalse(bar.is_virtual_method())
340e5dd7070Spatrick
341e5dd7070Spatrick    def test_is_abstract_record(self):
342e5dd7070Spatrick        """Ensure Cursor.is_abstract_record works."""
343e5dd7070Spatrick        source = 'struct X { virtual void x() = 0; }; struct Y : X { void x(); };'
344e5dd7070Spatrick        tu = get_tu(source, lang='cpp')
345e5dd7070Spatrick
346e5dd7070Spatrick        cls = get_cursor(tu, 'X')
347e5dd7070Spatrick        self.assertTrue(cls.is_abstract_record())
348e5dd7070Spatrick
349e5dd7070Spatrick        cls = get_cursor(tu, 'Y')
350e5dd7070Spatrick        self.assertFalse(cls.is_abstract_record())
351e5dd7070Spatrick
352e5dd7070Spatrick    def test_is_scoped_enum(self):
353e5dd7070Spatrick        """Ensure Cursor.is_scoped_enum works."""
354e5dd7070Spatrick        source = 'class X {}; enum RegularEnum {}; enum class ScopedEnum {};'
355e5dd7070Spatrick        tu = get_tu(source, lang='cpp')
356e5dd7070Spatrick
357e5dd7070Spatrick        cls = get_cursor(tu, 'X')
358e5dd7070Spatrick        regular_enum = get_cursor(tu, 'RegularEnum')
359e5dd7070Spatrick        scoped_enum = get_cursor(tu, 'ScopedEnum')
360e5dd7070Spatrick        self.assertIsNotNone(cls)
361e5dd7070Spatrick        self.assertIsNotNone(regular_enum)
362e5dd7070Spatrick        self.assertIsNotNone(scoped_enum)
363e5dd7070Spatrick
364e5dd7070Spatrick        self.assertFalse(cls.is_scoped_enum())
365e5dd7070Spatrick        self.assertFalse(regular_enum.is_scoped_enum())
366e5dd7070Spatrick        self.assertTrue(scoped_enum.is_scoped_enum())
367e5dd7070Spatrick
368e5dd7070Spatrick    def test_underlying_type(self):
369e5dd7070Spatrick        tu = get_tu('typedef int foo;')
370e5dd7070Spatrick        typedef = get_cursor(tu, 'foo')
371e5dd7070Spatrick        self.assertIsNotNone(typedef)
372e5dd7070Spatrick
373e5dd7070Spatrick        self.assertTrue(typedef.kind.is_declaration())
374e5dd7070Spatrick        underlying = typedef.underlying_typedef_type
375e5dd7070Spatrick        self.assertEqual(underlying.kind, TypeKind.INT)
376e5dd7070Spatrick
377e5dd7070Spatrick    def test_semantic_parent(self):
378e5dd7070Spatrick        tu = get_tu(kParentTest, 'cpp')
379e5dd7070Spatrick        curs = get_cursors(tu, 'f')
380e5dd7070Spatrick        decl = get_cursor(tu, 'C')
381e5dd7070Spatrick        self.assertEqual(len(curs), 2)
382e5dd7070Spatrick        self.assertEqual(curs[0].semantic_parent, curs[1].semantic_parent)
383e5dd7070Spatrick        self.assertEqual(curs[0].semantic_parent, decl)
384e5dd7070Spatrick
385e5dd7070Spatrick    def test_lexical_parent(self):
386e5dd7070Spatrick        tu = get_tu(kParentTest, 'cpp')
387e5dd7070Spatrick        curs = get_cursors(tu, 'f')
388e5dd7070Spatrick        decl = get_cursor(tu, 'C')
389e5dd7070Spatrick        self.assertEqual(len(curs), 2)
390e5dd7070Spatrick        self.assertNotEqual(curs[0].lexical_parent, curs[1].lexical_parent)
391e5dd7070Spatrick        self.assertEqual(curs[0].lexical_parent, decl)
392e5dd7070Spatrick        self.assertEqual(curs[1].lexical_parent, tu.cursor)
393e5dd7070Spatrick
394e5dd7070Spatrick    def test_enum_type(self):
395e5dd7070Spatrick        tu = get_tu('enum TEST { FOO=1, BAR=2 };')
396e5dd7070Spatrick        enum = get_cursor(tu, 'TEST')
397e5dd7070Spatrick        self.assertIsNotNone(enum)
398e5dd7070Spatrick
399e5dd7070Spatrick        self.assertEqual(enum.kind, CursorKind.ENUM_DECL)
400e5dd7070Spatrick        enum_type = enum.enum_type
401e5dd7070Spatrick        self.assertIn(enum_type.kind, (TypeKind.UINT, TypeKind.INT))
402e5dd7070Spatrick
403e5dd7070Spatrick    def test_enum_type_cpp(self):
404e5dd7070Spatrick        tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp")
405e5dd7070Spatrick        enum = get_cursor(tu, 'TEST')
406e5dd7070Spatrick        self.assertIsNotNone(enum)
407e5dd7070Spatrick
408e5dd7070Spatrick        self.assertEqual(enum.kind, CursorKind.ENUM_DECL)
409e5dd7070Spatrick        self.assertEqual(enum.enum_type.kind, TypeKind.LONGLONG)
410e5dd7070Spatrick
411e5dd7070Spatrick    def test_objc_type_encoding(self):
412e5dd7070Spatrick        tu = get_tu('int i;', lang='objc')
413e5dd7070Spatrick        i = get_cursor(tu, 'i')
414e5dd7070Spatrick
415e5dd7070Spatrick        self.assertIsNotNone(i)
416e5dd7070Spatrick        self.assertEqual(i.objc_type_encoding, 'i')
417e5dd7070Spatrick
418e5dd7070Spatrick    def test_enum_values(self):
419e5dd7070Spatrick        tu = get_tu('enum TEST { SPAM=1, EGG, HAM = EGG * 20};')
420e5dd7070Spatrick        enum = get_cursor(tu, 'TEST')
421e5dd7070Spatrick        self.assertIsNotNone(enum)
422e5dd7070Spatrick
423e5dd7070Spatrick        self.assertEqual(enum.kind, CursorKind.ENUM_DECL)
424e5dd7070Spatrick
425e5dd7070Spatrick        enum_constants = list(enum.get_children())
426e5dd7070Spatrick        self.assertEqual(len(enum_constants), 3)
427e5dd7070Spatrick
428e5dd7070Spatrick        spam, egg, ham = enum_constants
429e5dd7070Spatrick
430e5dd7070Spatrick        self.assertEqual(spam.kind, CursorKind.ENUM_CONSTANT_DECL)
431e5dd7070Spatrick        self.assertEqual(spam.enum_value, 1)
432e5dd7070Spatrick        self.assertEqual(egg.kind, CursorKind.ENUM_CONSTANT_DECL)
433e5dd7070Spatrick        self.assertEqual(egg.enum_value, 2)
434e5dd7070Spatrick        self.assertEqual(ham.kind, CursorKind.ENUM_CONSTANT_DECL)
435e5dd7070Spatrick        self.assertEqual(ham.enum_value, 40)
436e5dd7070Spatrick
437e5dd7070Spatrick    def test_enum_values_cpp(self):
438e5dd7070Spatrick        tu = get_tu('enum TEST : long long { SPAM = -1, HAM = 0x10000000000};', lang="cpp")
439e5dd7070Spatrick        enum = get_cursor(tu, 'TEST')
440e5dd7070Spatrick        self.assertIsNotNone(enum)
441e5dd7070Spatrick
442e5dd7070Spatrick        self.assertEqual(enum.kind, CursorKind.ENUM_DECL)
443e5dd7070Spatrick
444e5dd7070Spatrick        enum_constants = list(enum.get_children())
445e5dd7070Spatrick        self.assertEqual(len(enum_constants), 2)
446e5dd7070Spatrick
447e5dd7070Spatrick        spam, ham = enum_constants
448e5dd7070Spatrick
449e5dd7070Spatrick        self.assertEqual(spam.kind, CursorKind.ENUM_CONSTANT_DECL)
450e5dd7070Spatrick        self.assertEqual(spam.enum_value, -1)
451e5dd7070Spatrick        self.assertEqual(ham.kind, CursorKind.ENUM_CONSTANT_DECL)
452e5dd7070Spatrick        self.assertEqual(ham.enum_value, 0x10000000000)
453e5dd7070Spatrick
454e5dd7070Spatrick    def test_annotation_attribute(self):
455e5dd7070Spatrick        tu = get_tu('int foo (void) __attribute__ ((annotate("here be annotation attribute")));')
456e5dd7070Spatrick
457e5dd7070Spatrick        foo = get_cursor(tu, 'foo')
458e5dd7070Spatrick        self.assertIsNotNone(foo)
459e5dd7070Spatrick
460e5dd7070Spatrick        for c in foo.get_children():
461e5dd7070Spatrick            if c.kind == CursorKind.ANNOTATE_ATTR:
462e5dd7070Spatrick                self.assertEqual(c.displayname, "here be annotation attribute")
463e5dd7070Spatrick                break
464e5dd7070Spatrick        else:
465e5dd7070Spatrick            self.fail("Couldn't find annotation")
466e5dd7070Spatrick
467e5dd7070Spatrick    def test_annotation_template(self):
468e5dd7070Spatrick        annotation = '__attribute__ ((annotate("annotation")))'
469e5dd7070Spatrick        for source, kind in [
470e5dd7070Spatrick                ('int foo (T value) %s;', CursorKind.FUNCTION_TEMPLATE),
471e5dd7070Spatrick                ('class %s foo {};', CursorKind.CLASS_TEMPLATE),
472e5dd7070Spatrick        ]:
473e5dd7070Spatrick            source = 'template<typename T> ' + (source % annotation)
474e5dd7070Spatrick            tu = get_tu(source, lang="cpp")
475e5dd7070Spatrick
476e5dd7070Spatrick            foo = get_cursor(tu, 'foo')
477e5dd7070Spatrick            self.assertIsNotNone(foo)
478e5dd7070Spatrick            self.assertEqual(foo.kind, kind)
479e5dd7070Spatrick
480e5dd7070Spatrick            for c in foo.get_children():
481e5dd7070Spatrick                if c.kind == CursorKind.ANNOTATE_ATTR:
482e5dd7070Spatrick                    self.assertEqual(c.displayname, "annotation")
483e5dd7070Spatrick                    break
484e5dd7070Spatrick            else:
485e5dd7070Spatrick                self.fail("Couldn't find annotation for {}".format(kind))
486e5dd7070Spatrick
487e5dd7070Spatrick    def test_result_type(self):
488e5dd7070Spatrick        tu = get_tu('int foo();')
489e5dd7070Spatrick        foo = get_cursor(tu, 'foo')
490e5dd7070Spatrick
491e5dd7070Spatrick        self.assertIsNotNone(foo)
492e5dd7070Spatrick        t = foo.result_type
493e5dd7070Spatrick        self.assertEqual(t.kind, TypeKind.INT)
494e5dd7070Spatrick
495e5dd7070Spatrick    def test_result_type_objc_method_decl(self):
496e5dd7070Spatrick        code = """\
497e5dd7070Spatrick        @interface Interface : NSObject
498e5dd7070Spatrick        -(void)voidMethod;
499e5dd7070Spatrick        @end
500e5dd7070Spatrick        """
501e5dd7070Spatrick        tu = get_tu(code, lang='objc')
502e5dd7070Spatrick        cursor = get_cursor(tu, 'voidMethod')
503e5dd7070Spatrick        result_type = cursor.result_type
504e5dd7070Spatrick        self.assertEqual(cursor.kind, CursorKind.OBJC_INSTANCE_METHOD_DECL)
505e5dd7070Spatrick        self.assertEqual(result_type.kind, TypeKind.VOID)
506e5dd7070Spatrick
507e5dd7070Spatrick    def test_availability(self):
508e5dd7070Spatrick        tu = get_tu('class A { A(A const&) = delete; };', lang='cpp')
509e5dd7070Spatrick
510e5dd7070Spatrick        # AvailabilityKind.AVAILABLE
511e5dd7070Spatrick        cursor = get_cursor(tu, 'A')
512e5dd7070Spatrick        self.assertEqual(cursor.kind, CursorKind.CLASS_DECL)
513e5dd7070Spatrick        self.assertEqual(cursor.availability, AvailabilityKind.AVAILABLE)
514e5dd7070Spatrick
515e5dd7070Spatrick        # AvailabilityKind.NOT_AVAILABLE
516e5dd7070Spatrick        cursors = get_cursors(tu, 'A')
517e5dd7070Spatrick        for c in cursors:
518e5dd7070Spatrick            if c.kind == CursorKind.CONSTRUCTOR:
519e5dd7070Spatrick                self.assertEqual(c.availability, AvailabilityKind.NOT_AVAILABLE)
520e5dd7070Spatrick                break
521e5dd7070Spatrick        else:
522e5dd7070Spatrick            self.fail("Could not find cursor for deleted constructor")
523e5dd7070Spatrick
524e5dd7070Spatrick        # AvailabilityKind.DEPRECATED
525e5dd7070Spatrick        tu = get_tu('void test() __attribute__((deprecated));', lang='cpp')
526e5dd7070Spatrick        cursor = get_cursor(tu, 'test')
527e5dd7070Spatrick        self.assertEqual(cursor.availability, AvailabilityKind.DEPRECATED)
528e5dd7070Spatrick
529e5dd7070Spatrick        # AvailabilityKind.NOT_ACCESSIBLE is only used in the code completion results
530e5dd7070Spatrick
531e5dd7070Spatrick    def test_get_tokens(self):
532e5dd7070Spatrick        """Ensure we can map cursors back to tokens."""
533e5dd7070Spatrick        tu = get_tu('int foo(int i);')
534e5dd7070Spatrick        foo = get_cursor(tu, 'foo')
535e5dd7070Spatrick
536e5dd7070Spatrick        tokens = list(foo.get_tokens())
537e5dd7070Spatrick        self.assertEqual(len(tokens), 6)
538e5dd7070Spatrick        self.assertEqual(tokens[0].spelling, 'int')
539e5dd7070Spatrick        self.assertEqual(tokens[1].spelling, 'foo')
540e5dd7070Spatrick
541e5dd7070Spatrick    def test_get_token_cursor(self):
542e5dd7070Spatrick        """Ensure we can map tokens to cursors."""
543e5dd7070Spatrick        tu = get_tu('class A {}; int foo(A var = A());', lang='cpp')
544e5dd7070Spatrick        foo = get_cursor(tu, 'foo')
545e5dd7070Spatrick
546e5dd7070Spatrick        for cursor in foo.walk_preorder():
547e5dd7070Spatrick            if cursor.kind.is_expression() and not cursor.kind.is_statement():
548e5dd7070Spatrick                break
549e5dd7070Spatrick        else:
550e5dd7070Spatrick            self.fail("Could not find default value expression")
551e5dd7070Spatrick
552e5dd7070Spatrick        tokens = list(cursor.get_tokens())
553e5dd7070Spatrick        self.assertEqual(len(tokens), 4, [t.spelling for t in tokens])
554e5dd7070Spatrick        self.assertEqual(tokens[0].spelling, '=')
555e5dd7070Spatrick        self.assertEqual(tokens[1].spelling, 'A')
556e5dd7070Spatrick        self.assertEqual(tokens[2].spelling, '(')
557e5dd7070Spatrick        self.assertEqual(tokens[3].spelling, ')')
558e5dd7070Spatrick        t_cursor = tokens[1].cursor
559e5dd7070Spatrick        self.assertEqual(t_cursor.kind, CursorKind.TYPE_REF)
560e5dd7070Spatrick        r_cursor = t_cursor.referenced # should not raise an exception
561e5dd7070Spatrick        self.assertEqual(r_cursor.kind, CursorKind.CLASS_DECL)
562e5dd7070Spatrick
563e5dd7070Spatrick    def test_get_arguments(self):
564e5dd7070Spatrick        tu = get_tu('void foo(int i, int j);')
565e5dd7070Spatrick        foo = get_cursor(tu, 'foo')
566e5dd7070Spatrick        arguments = list(foo.get_arguments())
567e5dd7070Spatrick
568e5dd7070Spatrick        self.assertEqual(len(arguments), 2)
569e5dd7070Spatrick        self.assertEqual(arguments[0].spelling, "i")
570e5dd7070Spatrick        self.assertEqual(arguments[1].spelling, "j")
571e5dd7070Spatrick
572e5dd7070Spatrick    def test_get_num_template_arguments(self):
573e5dd7070Spatrick        tu = get_tu(kTemplateArgTest, lang='cpp')
574e5dd7070Spatrick        foos = get_cursors(tu, 'foo')
575e5dd7070Spatrick
576e5dd7070Spatrick        self.assertEqual(foos[1].get_num_template_arguments(), 3)
577e5dd7070Spatrick
578e5dd7070Spatrick    def test_get_template_argument_kind(self):
579e5dd7070Spatrick        tu = get_tu(kTemplateArgTest, lang='cpp')
580e5dd7070Spatrick        foos = get_cursors(tu, 'foo')
581e5dd7070Spatrick
582e5dd7070Spatrick        self.assertEqual(foos[1].get_template_argument_kind(0), TemplateArgumentKind.INTEGRAL)
583e5dd7070Spatrick        self.assertEqual(foos[1].get_template_argument_kind(1), TemplateArgumentKind.TYPE)
584e5dd7070Spatrick        self.assertEqual(foos[1].get_template_argument_kind(2), TemplateArgumentKind.INTEGRAL)
585e5dd7070Spatrick
586e5dd7070Spatrick    def test_get_template_argument_type(self):
587e5dd7070Spatrick        tu = get_tu(kTemplateArgTest, lang='cpp')
588e5dd7070Spatrick        foos = get_cursors(tu, 'foo')
589e5dd7070Spatrick
590e5dd7070Spatrick        self.assertEqual(foos[1].get_template_argument_type(1).kind, TypeKind.FLOAT)
591e5dd7070Spatrick
592e5dd7070Spatrick    def test_get_template_argument_value(self):
593e5dd7070Spatrick        tu = get_tu(kTemplateArgTest, lang='cpp')
594e5dd7070Spatrick        foos = get_cursors(tu, 'foo')
595e5dd7070Spatrick
596e5dd7070Spatrick        self.assertEqual(foos[1].get_template_argument_value(0), -7)
597e5dd7070Spatrick        self.assertEqual(foos[1].get_template_argument_value(2), True)
598e5dd7070Spatrick
599e5dd7070Spatrick    def test_get_template_argument_unsigned_value(self):
600e5dd7070Spatrick        tu = get_tu(kTemplateArgTest, lang='cpp')
601e5dd7070Spatrick        foos = get_cursors(tu, 'foo')
602e5dd7070Spatrick
603e5dd7070Spatrick        self.assertEqual(foos[1].get_template_argument_unsigned_value(0), 2 ** 32 - 7)
604e5dd7070Spatrick        self.assertEqual(foos[1].get_template_argument_unsigned_value(2), True)
605e5dd7070Spatrick
606e5dd7070Spatrick    def test_referenced(self):
607e5dd7070Spatrick        tu = get_tu('void foo(); void bar() { foo(); }')
608e5dd7070Spatrick        foo = get_cursor(tu, 'foo')
609e5dd7070Spatrick        bar = get_cursor(tu, 'bar')
610e5dd7070Spatrick        for c in bar.get_children():
611e5dd7070Spatrick            if c.kind == CursorKind.CALL_EXPR:
612e5dd7070Spatrick                self.assertEqual(c.referenced.spelling, foo.spelling)
613e5dd7070Spatrick                break
614e5dd7070Spatrick
615e5dd7070Spatrick    def test_mangled_name(self):
616e5dd7070Spatrick        kInputForMangling = """\
617e5dd7070Spatrick        int foo(int, int);
618e5dd7070Spatrick        """
619e5dd7070Spatrick        tu = get_tu(kInputForMangling, lang='cpp')
620e5dd7070Spatrick        foo = get_cursor(tu, 'foo')
621e5dd7070Spatrick
622e5dd7070Spatrick        # Since libclang does not link in targets, we cannot pass a triple to it
623e5dd7070Spatrick        # and force the target. To enable this test to pass on all platforms, accept
624e5dd7070Spatrick        # all valid manglings.
625e5dd7070Spatrick        # [c-index-test handles this by running the source through clang, emitting
626e5dd7070Spatrick        #  an AST file and running libclang on that AST file]
627e5dd7070Spatrick        self.assertIn(foo.mangled_name, ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH', '?foo@@YAHHH@Z'))
628