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