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 }