1import ctypes
2import gc
3
4from clang.cindex import CursorKind
5from clang.cindex import TemplateArgumentKind
6from clang.cindex import TranslationUnit
7from clang.cindex import TypeKind
8from .util import get_cursor
9from .util import get_cursors
10from .util import get_tu
11
12kInput = """\
13struct s0 {
14  int a;
15  int b;
16};
17
18struct s1;
19
20void f0(int a0, int a1) {
21  int l0, l1;
22
23  if (a0)
24    return;
25
26  for (;;) {
27    break;
28  }
29}
30"""
31
32def test_get_children():
33    tu = get_tu(kInput)
34
35    it = tu.cursor.get_children()
36    tu_nodes = list(it)
37
38    assert len(tu_nodes) == 3
39    for cursor in tu_nodes:
40        assert cursor.translation_unit is not None
41
42    assert tu_nodes[0] != tu_nodes[1]
43    assert tu_nodes[0].kind == CursorKind.STRUCT_DECL
44    assert tu_nodes[0].spelling == 's0'
45    assert tu_nodes[0].is_definition() == True
46    assert tu_nodes[0].location.file.name == 't.c'
47    assert tu_nodes[0].location.line == 1
48    assert tu_nodes[0].location.column == 8
49    assert tu_nodes[0].hash > 0
50    assert tu_nodes[0].translation_unit is not None
51
52    s0_nodes = list(tu_nodes[0].get_children())
53    assert len(s0_nodes) == 2
54    assert s0_nodes[0].kind == CursorKind.FIELD_DECL
55    assert s0_nodes[0].spelling == 'a'
56    assert s0_nodes[0].type.kind == TypeKind.INT
57    assert s0_nodes[1].kind == CursorKind.FIELD_DECL
58    assert s0_nodes[1].spelling == 'b'
59    assert s0_nodes[1].type.kind == TypeKind.INT
60
61    assert tu_nodes[1].kind == CursorKind.STRUCT_DECL
62    assert tu_nodes[1].spelling == 's1'
63    assert tu_nodes[1].displayname == 's1'
64    assert tu_nodes[1].is_definition() == False
65
66    assert tu_nodes[2].kind == CursorKind.FUNCTION_DECL
67    assert tu_nodes[2].spelling == 'f0'
68    assert tu_nodes[2].displayname == 'f0(int, int)'
69    assert tu_nodes[2].is_definition() == True
70
71def test_references():
72    """Ensure that references to TranslationUnit are kept."""
73    tu = get_tu('int x;')
74    cursors = list(tu.cursor.get_children())
75    assert len(cursors) > 0
76
77    cursor = cursors[0]
78    assert isinstance(cursor.translation_unit, TranslationUnit)
79
80    # Delete reference to TU and perform a full GC.
81    del tu
82    gc.collect()
83    assert isinstance(cursor.translation_unit, TranslationUnit)
84
85    # If the TU was destroyed, this should cause a segfault.
86    parent = cursor.semantic_parent
87
88def test_canonical():
89    source = 'struct X; struct X; struct X { int member; };'
90    tu = get_tu(source)
91
92    cursors = []
93    for cursor in tu.cursor.get_children():
94        if cursor.spelling == 'X':
95            cursors.append(cursor)
96
97    assert len(cursors) == 3
98    assert cursors[1].canonical == cursors[2].canonical
99
100def test_is_const_method():
101    """Ensure Cursor.is_const_method works."""
102    source = 'class X { void foo() const; void bar(); };'
103    tu = get_tu(source, lang='cpp')
104
105    cls = get_cursor(tu, 'X')
106    foo = get_cursor(tu, 'foo')
107    bar = get_cursor(tu, 'bar')
108    assert cls is not None
109    assert foo is not None
110    assert bar is not None
111
112    assert foo.is_const_method()
113    assert not bar.is_const_method()
114
115def test_is_converting_constructor():
116    """Ensure Cursor.is_converting_constructor works."""
117    source = 'class X { explicit X(int); X(double); X(); };'
118    tu = get_tu(source, lang='cpp')
119
120    xs = get_cursors(tu, 'X')
121
122    assert len(xs) == 4
123    assert xs[0].kind == CursorKind.CLASS_DECL
124    cs = xs[1:]
125    assert cs[0].kind == CursorKind.CONSTRUCTOR
126    assert cs[1].kind == CursorKind.CONSTRUCTOR
127    assert cs[2].kind == CursorKind.CONSTRUCTOR
128
129    assert not cs[0].is_converting_constructor()
130    assert cs[1].is_converting_constructor()
131    assert not cs[2].is_converting_constructor()
132
133
134def test_is_copy_constructor():
135    """Ensure Cursor.is_copy_constructor works."""
136    source = 'class X { X(); X(const X&); X(X&&); };'
137    tu = get_tu(source, lang='cpp')
138
139    xs = get_cursors(tu, 'X')
140    assert xs[0].kind == CursorKind.CLASS_DECL
141    cs = xs[1:]
142    assert cs[0].kind == CursorKind.CONSTRUCTOR
143    assert cs[1].kind == CursorKind.CONSTRUCTOR
144    assert cs[2].kind == CursorKind.CONSTRUCTOR
145
146    assert not cs[0].is_copy_constructor()
147    assert cs[1].is_copy_constructor()
148    assert not cs[2].is_copy_constructor()
149
150def test_is_default_constructor():
151    """Ensure Cursor.is_default_constructor works."""
152    source = 'class X { X(); X(int); };'
153    tu = get_tu(source, lang='cpp')
154
155    xs = get_cursors(tu, 'X')
156    assert xs[0].kind == CursorKind.CLASS_DECL
157    cs = xs[1:]
158    assert cs[0].kind == CursorKind.CONSTRUCTOR
159    assert cs[1].kind == CursorKind.CONSTRUCTOR
160
161    assert cs[0].is_default_constructor()
162    assert not cs[1].is_default_constructor()
163
164def test_is_move_constructor():
165    """Ensure Cursor.is_move_constructor works."""
166    source = 'class X { X(); X(const X&); X(X&&); };'
167    tu = get_tu(source, lang='cpp')
168
169    xs = get_cursors(tu, 'X')
170    assert xs[0].kind == CursorKind.CLASS_DECL
171    cs = xs[1:]
172    assert cs[0].kind == CursorKind.CONSTRUCTOR
173    assert cs[1].kind == CursorKind.CONSTRUCTOR
174    assert cs[2].kind == CursorKind.CONSTRUCTOR
175
176    assert not cs[0].is_move_constructor()
177    assert not cs[1].is_move_constructor()
178    assert cs[2].is_move_constructor()
179
180def test_is_default_method():
181    """Ensure Cursor.is_default_method works."""
182    source = 'class X { X() = default; }; class Y { Y(); };'
183    tu = get_tu(source, lang='cpp')
184
185    xs = get_cursors(tu, 'X')
186    ys = get_cursors(tu, 'Y')
187
188    assert len(xs) == 2
189    assert len(ys) == 2
190
191    xc = xs[1]
192    yc = ys[1]
193
194    assert xc.is_default_method()
195    assert not yc.is_default_method()
196
197def test_is_mutable_field():
198    """Ensure Cursor.is_mutable_field works."""
199    source = 'class X { int x_; mutable int y_; };'
200    tu = get_tu(source, lang='cpp')
201
202    cls = get_cursor(tu, 'X')
203    x_ = get_cursor(tu, 'x_')
204    y_ = get_cursor(tu, 'y_')
205    assert cls is not None
206    assert x_ is not None
207    assert y_ is not None
208
209    assert not x_.is_mutable_field()
210    assert y_.is_mutable_field()
211
212def test_is_static_method():
213    """Ensure Cursor.is_static_method works."""
214
215    source = 'class X { static void foo(); void bar(); };'
216    tu = get_tu(source, lang='cpp')
217
218    cls = get_cursor(tu, 'X')
219    foo = get_cursor(tu, 'foo')
220    bar = get_cursor(tu, 'bar')
221    assert cls is not None
222    assert foo is not None
223    assert bar is not None
224
225    assert foo.is_static_method()
226    assert not bar.is_static_method()
227
228def test_is_pure_virtual_method():
229    """Ensure Cursor.is_pure_virtual_method works."""
230    source = 'class X { virtual void foo() = 0; virtual void bar(); };'
231    tu = get_tu(source, lang='cpp')
232
233    cls = get_cursor(tu, 'X')
234    foo = get_cursor(tu, 'foo')
235    bar = get_cursor(tu, 'bar')
236    assert cls is not None
237    assert foo is not None
238    assert bar is not None
239
240    assert foo.is_pure_virtual_method()
241    assert not bar.is_pure_virtual_method()
242
243def test_is_virtual_method():
244    """Ensure Cursor.is_virtual_method works."""
245    source = 'class X { virtual void foo(); void bar(); };'
246    tu = get_tu(source, lang='cpp')
247
248    cls = get_cursor(tu, 'X')
249    foo = get_cursor(tu, 'foo')
250    bar = get_cursor(tu, 'bar')
251    assert cls is not None
252    assert foo is not None
253    assert bar is not None
254
255    assert foo.is_virtual_method()
256    assert not bar.is_virtual_method()
257
258def test_is_scoped_enum():
259    """Ensure Cursor.is_scoped_enum works."""
260    source = 'class X {}; enum RegularEnum {}; enum class ScopedEnum {};'
261    tu = get_tu(source, lang='cpp')
262
263    cls = get_cursor(tu, 'X')
264    regular_enum = get_cursor(tu, 'RegularEnum')
265    scoped_enum = get_cursor(tu, 'ScopedEnum')
266    assert cls is not None
267    assert regular_enum is not None
268    assert scoped_enum is not None
269
270    assert not cls.is_scoped_enum()
271    assert not regular_enum.is_scoped_enum()
272    assert scoped_enum.is_scoped_enum()
273
274def test_underlying_type():
275    tu = get_tu('typedef int foo;')
276    typedef = get_cursor(tu, 'foo')
277    assert typedef is not None
278
279    assert typedef.kind.is_declaration()
280    underlying = typedef.underlying_typedef_type
281    assert underlying.kind == TypeKind.INT
282
283kParentTest = """\
284        class C {
285            void f();
286        }
287
288        void C::f() { }
289    """
290def test_semantic_parent():
291    tu = get_tu(kParentTest, 'cpp')
292    curs = get_cursors(tu, 'f')
293    decl = get_cursor(tu, 'C')
294    assert(len(curs) == 2)
295    assert(curs[0].semantic_parent == curs[1].semantic_parent)
296    assert(curs[0].semantic_parent == decl)
297
298def test_lexical_parent():
299    tu = get_tu(kParentTest, 'cpp')
300    curs = get_cursors(tu, 'f')
301    decl = get_cursor(tu, 'C')
302    assert(len(curs) == 2)
303    assert(curs[0].lexical_parent != curs[1].lexical_parent)
304    assert(curs[0].lexical_parent == decl)
305    assert(curs[1].lexical_parent == tu.cursor)
306
307def test_enum_type():
308    tu = get_tu('enum TEST { FOO=1, BAR=2 };')
309    enum = get_cursor(tu, 'TEST')
310    assert enum is not None
311
312    assert enum.kind == CursorKind.ENUM_DECL
313    enum_type = enum.enum_type
314    assert enum_type.kind == TypeKind.UINT
315
316def test_enum_type_cpp():
317    tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp")
318    enum = get_cursor(tu, 'TEST')
319    assert enum is not None
320
321    assert enum.kind == CursorKind.ENUM_DECL
322    assert enum.enum_type.kind == TypeKind.LONGLONG
323
324def test_objc_type_encoding():
325    tu = get_tu('int i;', lang='objc')
326    i = get_cursor(tu, 'i')
327
328    assert i is not None
329    assert i.objc_type_encoding == 'i'
330
331def test_enum_values():
332    tu = get_tu('enum TEST { SPAM=1, EGG, HAM = EGG * 20};')
333    enum = get_cursor(tu, 'TEST')
334    assert enum is not None
335
336    assert enum.kind == CursorKind.ENUM_DECL
337
338    enum_constants = list(enum.get_children())
339    assert len(enum_constants) == 3
340
341    spam, egg, ham = enum_constants
342
343    assert spam.kind == CursorKind.ENUM_CONSTANT_DECL
344    assert spam.enum_value == 1
345    assert egg.kind == CursorKind.ENUM_CONSTANT_DECL
346    assert egg.enum_value == 2
347    assert ham.kind == CursorKind.ENUM_CONSTANT_DECL
348    assert ham.enum_value == 40
349
350def test_enum_values_cpp():
351    tu = get_tu('enum TEST : long long { SPAM = -1, HAM = 0x10000000000};', lang="cpp")
352    enum = get_cursor(tu, 'TEST')
353    assert enum is not None
354
355    assert enum.kind == CursorKind.ENUM_DECL
356
357    enum_constants = list(enum.get_children())
358    assert len(enum_constants) == 2
359
360    spam, ham = enum_constants
361
362    assert spam.kind == CursorKind.ENUM_CONSTANT_DECL
363    assert spam.enum_value == -1
364    assert ham.kind == CursorKind.ENUM_CONSTANT_DECL
365    assert ham.enum_value == 0x10000000000
366
367def test_annotation_attribute():
368    tu = get_tu('int foo (void) __attribute__ ((annotate("here be annotation attribute")));')
369
370    foo = get_cursor(tu, 'foo')
371    assert foo is not None
372
373    for c in foo.get_children():
374        if c.kind == CursorKind.ANNOTATE_ATTR:
375            assert c.displayname == "here be annotation attribute"
376            break
377    else:
378        assert False, "Couldn't find annotation"
379
380def test_result_type():
381    tu = get_tu('int foo();')
382    foo = get_cursor(tu, 'foo')
383
384    assert foo is not None
385    t = foo.result_type
386    assert t.kind == TypeKind.INT
387
388def test_get_tokens():
389    """Ensure we can map cursors back to tokens."""
390    tu = get_tu('int foo(int i);')
391    foo = get_cursor(tu, 'foo')
392
393    tokens = list(foo.get_tokens())
394    assert len(tokens) == 6
395    assert tokens[0].spelling == 'int'
396    assert tokens[1].spelling == 'foo'
397
398def test_get_token_cursor():
399    """Ensure we can map tokens to cursors."""
400    tu = get_tu('class A {}; int foo(A var = A());', lang='cpp')
401    foo = get_cursor(tu, 'foo')
402
403    for cursor in foo.walk_preorder():
404        if cursor.kind.is_expression() and not cursor.kind.is_statement():
405            break
406    else:
407        assert False, "Could not find default value expression"
408
409    tokens = list(cursor.get_tokens())
410    assert len(tokens) == 4, [t.spelling for t in tokens]
411    assert tokens[0].spelling == '='
412    assert tokens[1].spelling == 'A'
413    assert tokens[2].spelling == '('
414    assert tokens[3].spelling == ')'
415    t_cursor = tokens[1].cursor
416    assert t_cursor.kind == CursorKind.TYPE_REF
417    r_cursor = t_cursor.referenced # should not raise an exception
418    assert r_cursor.kind == CursorKind.CLASS_DECL
419
420def test_get_arguments():
421    tu = get_tu('void foo(int i, int j);')
422    foo = get_cursor(tu, 'foo')
423    arguments = list(foo.get_arguments())
424
425    assert len(arguments) == 2
426    assert arguments[0].spelling == "i"
427    assert arguments[1].spelling == "j"
428
429kTemplateArgTest = """\
430        template <int kInt, typename T, bool kBool>
431        void foo();
432
433        template<>
434        void foo<-7, float, true>();
435    """
436
437def test_get_num_template_arguments():
438    tu = get_tu(kTemplateArgTest, lang='cpp')
439    foos = get_cursors(tu, 'foo')
440
441    assert foos[1].get_num_template_arguments() == 3
442
443def test_get_template_argument_kind():
444    tu = get_tu(kTemplateArgTest, lang='cpp')
445    foos = get_cursors(tu, 'foo')
446
447    assert foos[1].get_template_argument_kind(0) == TemplateArgumentKind.INTEGRAL
448    assert foos[1].get_template_argument_kind(1) == TemplateArgumentKind.TYPE
449    assert foos[1].get_template_argument_kind(2) == TemplateArgumentKind.INTEGRAL
450
451def test_get_template_argument_type():
452    tu = get_tu(kTemplateArgTest, lang='cpp')
453    foos = get_cursors(tu, 'foo')
454
455    assert foos[1].get_template_argument_type(1).kind == TypeKind.FLOAT
456
457def test_get_template_argument_value():
458    tu = get_tu(kTemplateArgTest, lang='cpp')
459    foos = get_cursors(tu, 'foo')
460
461    assert foos[1].get_template_argument_value(0) == -7
462    assert foos[1].get_template_argument_value(2) == True
463
464def test_get_template_argument_unsigned_value():
465    tu = get_tu(kTemplateArgTest, lang='cpp')
466    foos = get_cursors(tu, 'foo')
467
468    assert foos[1].get_template_argument_unsigned_value(0) == 2 ** 32 - 7
469    assert foos[1].get_template_argument_unsigned_value(2) == True
470
471def test_referenced():
472    tu = get_tu('void foo(); void bar() { foo(); }')
473    foo = get_cursor(tu, 'foo')
474    bar = get_cursor(tu, 'bar')
475    for c in bar.get_children():
476        if c.kind == CursorKind.CALL_EXPR:
477            assert c.referenced.spelling == foo.spelling
478            break
479
480def test_mangled_name():
481    kInputForMangling = """\
482    int foo(int, int);
483    """
484    tu = get_tu(kInputForMangling, lang='cpp')
485    foo = get_cursor(tu, 'foo')
486
487    # Since libclang does not link in targets, we cannot pass a triple to it
488    # and force the target. To enable this test to pass on all platforms, accept
489    # all valid manglings.
490    # [c-index-test handles this by running the source through clang, emitting
491    #  an AST file and running libclang on that AST file]
492    assert foo.mangled_name in ('_Z3fooii', '__Z3fooii', '?foo@@YAHHH')
493