1from clang.cindex import CursorKind
2from clang.cindex import TypeKind
3from .util import get_cursor
4from .util import get_cursors
5from .util import get_tu
6
7kInput = """\
8// FIXME: Find nicer way to drop builtins and other cruft.
9int start_decl;
10
11struct s0 {
12  int a;
13  int b;
14};
15
16struct s1;
17
18void f0(int a0, int a1) {
19  int l0, l1;
20
21  if (a0)
22    return;
23
24  for (;;) {
25    break;
26  }
27}
28"""
29
30def test_get_children():
31    tu = get_tu(kInput)
32
33    # Skip until past start_decl.
34    it = tu.cursor.get_children()
35    while it.next().spelling != 'start_decl':
36        pass
37
38    tu_nodes = list(it)
39
40    assert len(tu_nodes) == 3
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 == 4
48    assert tu_nodes[0].location.column == 8
49    assert tu_nodes[0].hash > 0
50
51    s0_nodes = list(tu_nodes[0].get_children())
52    assert len(s0_nodes) == 2
53    assert s0_nodes[0].kind == CursorKind.FIELD_DECL
54    assert s0_nodes[0].spelling == 'a'
55    assert s0_nodes[0].type.kind == TypeKind.INT
56    assert s0_nodes[1].kind == CursorKind.FIELD_DECL
57    assert s0_nodes[1].spelling == 'b'
58    assert s0_nodes[1].type.kind == TypeKind.INT
59
60    assert tu_nodes[1].kind == CursorKind.STRUCT_DECL
61    assert tu_nodes[1].spelling == 's1'
62    assert tu_nodes[1].displayname == 's1'
63    assert tu_nodes[1].is_definition() == False
64
65    assert tu_nodes[2].kind == CursorKind.FUNCTION_DECL
66    assert tu_nodes[2].spelling == 'f0'
67    assert tu_nodes[2].displayname == 'f0(int, int)'
68    assert tu_nodes[2].is_definition() == True
69
70def test_canonical():
71    source = 'struct X; struct X; struct X { int member; };'
72    tu = get_tu(source)
73
74    cursors = []
75    for cursor in tu.cursor.get_children():
76        if cursor.spelling == 'X':
77            cursors.append(cursor)
78
79    assert len(cursors) == 3
80    assert cursors[1].canonical == cursors[2].canonical
81
82def test_underlying_type():
83    tu = get_tu('typedef int foo;')
84    typedef = get_cursor(tu, 'foo')
85    assert typedef is not None
86
87    assert typedef.kind.is_declaration()
88    underlying = typedef.underlying_typedef_type
89    assert underlying.kind == TypeKind.INT
90
91kParentTest = """\
92        class C {
93            void f();
94        }
95
96        void C::f() { }
97    """
98def test_semantic_parent():
99    tu = get_tu(kParentTest, 'cpp')
100    curs = get_cursors(tu, 'f')
101    decl = get_cursor(tu, 'C')
102    assert(len(curs) == 2)
103    assert(curs[0].semantic_parent == curs[1].semantic_parent)
104    assert(curs[0].semantic_parent == decl)
105
106def test_lexical_parent():
107    tu = get_tu(kParentTest, 'cpp')
108    curs = get_cursors(tu, 'f')
109    decl = get_cursor(tu, 'C')
110    assert(len(curs) == 2)
111    assert(curs[0].lexical_parent != curs[1].lexical_parent)
112    assert(curs[0].lexical_parent == decl)
113    assert(curs[1].lexical_parent == tu.cursor)
114
115def test_enum_type():
116    tu = get_tu('enum TEST { FOO=1, BAR=2 };')
117    enum = get_cursor(tu, 'TEST')
118    assert enum is not None
119
120    assert enum.kind == CursorKind.ENUM_DECL
121    enum_type = enum.enum_type
122    assert enum_type.kind == TypeKind.UINT
123
124def test_enum_type_cpp():
125    tu = get_tu('enum TEST : long long { FOO=1, BAR=2 };', lang="cpp")
126    enum = get_cursor(tu, 'TEST')
127    assert enum is not None
128
129    assert enum.kind == CursorKind.ENUM_DECL
130    assert enum.enum_type.kind == TypeKind.LONGLONG
131
132def test_objc_type_encoding():
133    tu = get_tu('int i;', lang='objc')
134    i = get_cursor(tu, 'i')
135
136    assert i is not None
137    assert i.objc_type_encoding == 'i'
138
139def test_enum_values():
140    tu = get_tu('enum TEST { SPAM=1, EGG, HAM = EGG * 20};')
141    enum = get_cursor(tu, 'TEST')
142    assert enum is not None
143
144    assert enum.kind == CursorKind.ENUM_DECL
145
146    enum_constants = list(enum.get_children())
147    assert len(enum_constants) == 3
148
149    spam, egg, ham = enum_constants
150
151    assert spam.kind == CursorKind.ENUM_CONSTANT_DECL
152    assert spam.enum_value == 1
153    assert egg.kind == CursorKind.ENUM_CONSTANT_DECL
154    assert egg.enum_value == 2
155    assert ham.kind == CursorKind.ENUM_CONSTANT_DECL
156    assert ham.enum_value == 40
157
158def test_enum_values_cpp():
159    tu = get_tu('enum TEST : long long { SPAM = -1, HAM = 0x10000000000};', lang="cpp")
160    enum = get_cursor(tu, 'TEST')
161    assert enum is not None
162
163    assert enum.kind == CursorKind.ENUM_DECL
164
165    enum_constants = list(enum.get_children())
166    assert len(enum_constants) == 2
167
168    spam, ham = enum_constants
169
170    assert spam.kind == CursorKind.ENUM_CONSTANT_DECL
171    assert spam.enum_value == -1
172    assert ham.kind == CursorKind.ENUM_CONSTANT_DECL
173    assert ham.enum_value == 0x10000000000
174
175def test_annotation_attribute():
176    tu = get_tu('int foo (void) __attribute__ ((annotate("here be annotation attribute")));')
177
178    foo = get_cursor(tu, 'foo')
179    assert foo is not None
180
181    for c in foo.get_children():
182        if c.kind == CursorKind.ANNOTATE_ATTR:
183            assert c.displayname == "here be annotation attribute"
184            break
185    else:
186        assert False, "Couldn't find annotation"
187
188def test_result_type():
189    tu = get_tu('int foo();')
190    foo = get_cursor(tu, 'foo')
191
192    assert foo is not None
193    t = foo.result_type
194    assert t.kind == TypeKind.INT
195