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