1 module parse.cooked;
2 
3 import test.infra;
4 import clang;
5 
6 @("visitChildren C++ file with one simple struct")
7 @safe unittest {
8     with(NewTranslationUnit("foo.cpp",
9                             q{ struct Struct { int int_; double double_; }; }))
10     {
11         translUnit.cursor.visitChildren(
12             (cursor, parent) {
13 
14                 import clang: Cursor;
15 
16                 static int cursorIndex;
17 
18                 switch(cursorIndex) {
19 
20                 default:
21                     assert(false);
22 
23                 case 0:
24                     cursor.kind.shouldEqual(Cursor.Kind.StructDecl);
25                     parent.kind.shouldEqual(Cursor.Kind.TranslationUnit);
26                     break;
27 
28                 case 1:
29                     cursor.kind.shouldEqual(Cursor.Kind.FieldDecl);
30                     parent.kind.shouldEqual(Cursor.Kind.StructDecl);
31                     break;
32 
33                 case 2:
34                     cursor.kind.shouldEqual(Cursor.Kind.FieldDecl);
35                     parent.kind.shouldEqual(Cursor.Kind.StructDecl);
36                     break;
37                 }
38 
39                 ++cursorIndex;
40 
41 
42                 return ChildVisitResult.Recurse;
43             }
44         );
45     }
46 }
47 
48 
49 @("visitChildren C++ file with one simple struct and throwing visitor")
50 @safe unittest {
51     with(NewTranslationUnit("foo.cpp",
52                             q{ struct Struct { int int_; double double_; }; }))
53     {
54         translUnit.cursor.visitChildren(
55             (cursor, parent) {
56                 int i;
57                 if(i % 2 == 0)
58                     throw new Exception("oops");
59                 return ChildVisitResult.Recurse;
60             }
61         ).shouldThrowWithMessage("oops");
62     }
63 
64 }
65 
66 @("foreach(cursor, parent) C++ file with one simple struct")
67 @safe unittest {
68     with(NewTranslationUnit("foo.cpp",
69                             q{ struct Struct { int int_; double double_; }; }))
70     {
71         foreach(cursor, parent; translUnit.cursor) {
72 
73             import clang: Cursor;
74 
75             static int cursorIndex;
76 
77             switch(cursorIndex) {
78 
79             default:
80                 assert(false);
81 
82             case 0:
83                 cursor.kind.shouldEqual(Cursor.Kind.StructDecl);
84                 parent.kind.shouldEqual(Cursor.Kind.TranslationUnit);
85                 break;
86 
87             case 1:
88                 cursor.kind.shouldEqual(Cursor.Kind.FieldDecl);
89                 parent.kind.shouldEqual(Cursor.Kind.StructDecl);
90                 break;
91 
92             case 2:
93                 cursor.kind.shouldEqual(Cursor.Kind.FieldDecl);
94                 parent.kind.shouldEqual(Cursor.Kind.StructDecl);
95                 break;
96             }
97 
98             ++cursorIndex;
99         }
100     }
101 }
102 
103 @("foreach(cursor) C++ file with one simple struct")
104 @safe unittest {
105     with(NewTranslationUnit("foo.cpp",
106                             q{ struct Struct { int int_; double double_; }; }))
107     {
108         foreach(cursor; translUnit.cursor) {
109 
110             import clang: Cursor;
111 
112             static int cursorIndex;
113 
114             switch(cursorIndex) {
115 
116             default:
117                 assert(false);
118 
119             case 0:
120                 cursor.kind.shouldEqual(Cursor.Kind.StructDecl);
121                 break;
122 
123             case 1:
124                 cursor.kind.shouldEqual(Cursor.Kind.FieldDecl);
125                 break;
126 
127             case 2:
128                 cursor.kind.shouldEqual(Cursor.Kind.FieldDecl);
129                 break;
130             }
131 
132             ++cursorIndex;
133         }
134     }
135 }
136 
137 @("cursor.children C++ file with one simple struct")
138 @safe unittest {
139     import std.algorithm: map;
140 
141     with(NewTranslationUnit("foo.cpp",
142                             q{ struct Struct { int int_; double double_; }; }))
143     {
144         import clang: Cursor;
145 
146         const cursor = translUnit.cursor;
147         with(Cursor.Kind) {
148             cursor.children.map!(a => a.kind).shouldEqual([StructDecl]);
149             cursor.children[0].children.map!(a => a.kind).shouldEqual(
150                 [FieldDecl, FieldDecl]
151             );
152         }
153     }
154 }
155 
156 @("Function return type should have valid cx")
157 @safe unittest {
158     import clang.c.index: CXType_Pointer;
159     with(NewTranslationUnit("foo.cpp",
160                             q{
161                                 const char* newString();
162                             }))
163     {
164         import clang: Cursor;
165 
166         const cursor = translUnit.cursor;
167         cursor.children.length.shouldEqual(1);
168         const function_ = cursor.children[0];
169         function_.kind.shouldEqual(Cursor.Kind.FunctionDecl);
170         function_.returnType.kind.shouldEqual(Type.Kind.Pointer);
171         function_.returnType.cx.kind.shouldEqual(CXType_Pointer);
172     }
173 
174 }