1 /** 2 * Copyright: Copyright (c) 2012 Jacob Carlborg. All rights reserved. 3 * Authors: Jacob Carlborg 4 * Version: Initial created: Jan 29, 2012 5 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) 6 */ 7 module clang.Visitor; 8 9 import clang.c.index; 10 import clang.Cursor; 11 12 struct Visitor 13 { 14 alias int delegate (ref Cursor, ref Cursor) Delegate; 15 alias int delegate (Delegate dg) OpApply; 16 17 private CXCursor cursor; 18 19 this (CXCursor cursor) 20 { 21 this.cursor = cursor; 22 } 23 24 this (Cursor cursor) 25 { 26 this.cursor = cursor.cx; 27 } 28 29 int opApply (Delegate dg) 30 { 31 auto data = OpApplyData(dg); 32 clang_visitChildren(cursor, &visitorFunction, cast(CXClientData) &data); 33 34 return data.returnCode; 35 } 36 37 private: 38 39 extern (C) static CXChildVisitResult visitorFunction (CXCursor cursor, CXCursor parent, CXClientData data) 40 { 41 auto tmp = cast(OpApplyData*) data; 42 43 with (CXChildVisitResult) 44 { 45 auto dCursor = Cursor(cursor); 46 auto dParent = Cursor(parent); 47 auto r = tmp.dg(dCursor, dParent); 48 tmp.returnCode = r; 49 return r ? CXChildVisit_Break : CXChildVisit_Continue; 50 } 51 } 52 53 static struct OpApplyData 54 { 55 int returnCode; 56 Delegate dg; 57 58 this (Delegate dg) 59 { 60 this.dg = dg; 61 } 62 } 63 64 template Constructors () 65 { 66 private Visitor visitor; 67 68 this (Visitor visitor) 69 { 70 this.visitor = visitor; 71 } 72 73 this (CXCursor cursor) 74 { 75 visitor = Visitor(cursor); 76 } 77 78 this (Cursor cursor) 79 { 80 visitor = Visitor(cursor); 81 } 82 } 83 } 84 85 struct DeclarationVisitor 86 { 87 mixin Visitor.Constructors; 88 89 int opApply (Visitor.Delegate dg) 90 { 91 foreach (cursor, parent ; visitor) 92 if (cursor.isDeclaration) 93 if (auto result = dg(cursor, parent)) 94 return result; 95 96 return 0; 97 } 98 } 99 100 struct TypedVisitor (CXCursorKind kind) 101 { 102 private Visitor visitor; 103 104 this (Visitor visitor) 105 { 106 this.visitor = visitor; 107 } 108 109 this (CXCursor cursor) 110 { 111 this(Visitor(cursor)); 112 } 113 114 this (Cursor cursor) 115 { 116 this(cursor.cx); 117 } 118 119 int opApply (Visitor.Delegate dg) 120 { 121 foreach (cursor, parent ; visitor) 122 if (cursor.kind == kind) 123 if (auto result = dg(cursor, parent)) 124 return result; 125 126 return 0; 127 } 128 } 129 130 alias TypedVisitor!(CXCursorKind.CXCursor_ObjCInstanceMethodDecl) ObjCInstanceMethodVisitor; 131 alias TypedVisitor!(CXCursorKind.CXCursor_ObjCClassMethodDecl) ObjCClassMethodVisitor; 132 alias TypedVisitor!(CXCursorKind.CXCursor_ObjCPropertyDecl) ObjCPropertyVisitor; 133 alias TypedVisitor!(CXCursorKind.CXCursor_ObjCProtocolRef) ObjCProtocolVisitor; 134 135 struct ParamVisitor 136 { 137 mixin Visitor.Constructors; 138 139 int opApply (int delegate (ref ParamCursor) dg) 140 { 141 foreach (cursor, parent ; visitor) 142 if (cursor.kind == CXCursorKind.CXCursor_ParmDecl) 143 { 144 auto paramCursor = ParamCursor(cursor); 145 146 if (auto result = dg(paramCursor)) 147 return result; 148 } 149 150 return 0; 151 } 152 153 @property size_t length () 154 { 155 auto type = Cursor(visitor.cursor).type; 156 157 if (type.isValid) 158 return type.func.arguments.length; 159 160 else 161 { 162 size_t i; 163 164 foreach (_ ; this) 165 i++; 166 167 return i; 168 } 169 } 170 171 @property bool any () 172 { 173 return length > 0; 174 } 175 176 @property bool isEmpty () 177 { 178 return !any; 179 } 180 181 @property ParamCursor first () 182 { 183 assert(any, "Cannot get the first parameter of an empty parameter list"); 184 185 foreach (c ; this) 186 return c; 187 188 assert(0, "Cannot get the first parameter of an empty parameter list"); 189 } 190 }