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 11 import clang.Cursor; 12 import clang.TranslationUnit; 13 14 struct Visitor { 15 alias Delegate = int delegate(ref Cursor, ref Cursor); 16 alias OpApply = int delegate(Delegate dg); 17 18 @safe: 19 20 private CXCursor cursor; 21 22 this(CXCursor cursor) { 23 this.cursor = cursor; 24 } 25 26 this(Cursor cursor) { 27 this.cursor = cursor.cx; 28 } 29 30 /** 31 * Trusted: assuming the LLVM function do NOT abuse the pointer in any way. 32 */ 33 int opApply(Delegate dg) @trusted { 34 if (dg is null) 35 return 0; 36 37 auto data = OpApplyData(dg); 38 clang_visitChildren(cursor, &visitorFunction, cast(CXClientData)&data); 39 40 return data.returnCode; 41 } 42 43 /** 44 * Trusted: assuming the LLVM function do NOT abuse the pointer in any way. 45 */ 46 int opApply(int delegate(ref Cursor) dg) @trusted { 47 int wrapper(ref Cursor cursor, ref Cursor) { 48 return dg(cursor); 49 } 50 51 if (dg is null) 52 return 0; 53 54 auto data = OpApplyData(&wrapper); 55 clang_visitChildren(cursor, &visitorFunction, cast(CXClientData)&data); 56 57 return data.returnCode; 58 } 59 60 private: 61 62 extern (C) static CXChildVisitResult visitorFunction(CXCursor cursor, 63 CXCursor parent, CXClientData data) @trusted { 64 if (data is null) 65 return CXChildVisitResult.continue_; 66 67 auto tmp = cast(OpApplyData*) data; 68 69 with (CXChildVisitResult) { 70 auto dCursor = Cursor(cursor); 71 auto dParent = Cursor(parent); 72 auto r = tmp.dg(dCursor, dParent); 73 tmp.returnCode = r; 74 return r ? break_ : continue_; 75 } 76 } 77 78 static struct OpApplyData { 79 int returnCode; 80 Delegate dg; 81 82 this(Delegate dg) { 83 this.dg = dg; 84 } 85 } 86 87 template Constructors() { 88 private Visitor visitor; 89 90 this(Visitor visitor) { 91 this.visitor = visitor; 92 } 93 94 this(CXCursor cursor) { 95 visitor = Visitor(cursor); 96 } 97 98 this(Cursor cursor) { 99 visitor = Visitor(cursor); 100 } 101 } 102 } 103 104 @safe struct InOrderVisitor { 105 alias int delegate(ref Cursor, ref Cursor) Delegate; 106 107 private Cursor cursor; 108 109 this(CXCursor cursor) { 110 this.cursor = Cursor(cursor); 111 } 112 113 this(Cursor cursor) { 114 this.cursor = cursor; 115 } 116 117 int opApply(Delegate dg) @trusted { 118 import std.array; 119 120 auto visitor = Visitor(cursor); 121 int result = 0; 122 123 auto macrosAppender = appender!(Cursor[])(); 124 size_t itr = 0; 125 126 foreach (cursor, _; visitor) { 127 if (cursor.isPreprocessing) 128 macrosAppender.put(cursor); 129 } 130 131 auto macros = macrosAppender.data; 132 auto query = cursor.translationUnit.relativeLocationAccessorImpl(macros); 133 134 ulong macroIndex = macros.length != 0 ? query(macros[0].location) : ulong.max; 135 136 size_t jtr = 0; 137 138 foreach (cursor, parent; visitor) { 139 if (!cursor.isPreprocessing) { 140 ulong cursorIndex = query(cursor.location); 141 142 while (macroIndex < cursorIndex) { 143 Cursor macroParent = macros[jtr].semanticParent; 144 145 result = dg(macros[jtr], macroParent); 146 147 if (result) 148 return result; 149 150 ++jtr; 151 152 macroIndex = jtr < macros.length ? query(macros[jtr].location) : ulong.max; 153 } 154 155 result = dg(cursor, parent); 156 157 if (result) 158 return result; 159 } 160 } 161 162 while (jtr < macros.length) { 163 Cursor macroParent = macros[jtr].semanticParent; 164 165 result = dg(macros[jtr], macroParent); 166 167 if (result) 168 return result; 169 170 ++jtr; 171 } 172 173 return result; 174 } 175 } 176 177 struct DeclarationVisitor { 178 mixin Visitor.Constructors; 179 180 int opApply(Visitor.Delegate dg) { 181 foreach (cursor, parent; visitor) { 182 if (cursor.isDeclaration) { 183 if (auto result = dg(cursor, parent)) { 184 return result; 185 } 186 } 187 } 188 189 return 0; 190 } 191 } 192 193 struct TypedVisitor(CXCursorKind kind) { 194 private Visitor visitor; 195 196 this(Visitor visitor) { 197 this.visitor = visitor; 198 } 199 200 this(Cursor cursor) { 201 this.visitor = Visitor(cursor); 202 } 203 204 int opApply(Visitor.Delegate dg) { 205 foreach (cursor, parent; visitor) { 206 if (cursor.kind == kind) { 207 if (auto result = dg(cursor, parent)) { 208 return result; 209 } 210 } 211 } 212 213 return 0; 214 } 215 } 216 217 alias ObjCInstanceMethodVisitor = TypedVisitor!(CXCursorKind.objCInstanceMethodDecl); 218 alias ObjCClassMethodVisitor = TypedVisitor!(CXCursorKind.objCClassMethodDecl); 219 alias ObjCPropertyVisitor = TypedVisitor!(CXCursorKind.objCPropertyDecl); 220 alias ObjCProtocolVisitor = TypedVisitor!(CXCursorKind.objCProtocolRef); 221 222 struct ParamVisitor { 223 mixin Visitor.Constructors; 224 225 int opApply(int delegate(ref ParamCursor) dg) { 226 foreach (cursor, parent; visitor) { 227 if (cursor.kind == CXCursorKind.parmDecl) { 228 auto paramCursor = ParamCursor(cursor); 229 230 if (auto result = dg(paramCursor)) 231 return result; 232 } 233 } 234 235 return 0; 236 } 237 238 @property size_t length() { 239 auto type = Cursor(visitor.cursor).type; 240 241 if (type.isValid) 242 return type.func.arguments.length; 243 244 else { 245 size_t i; 246 247 foreach (_; this) 248 i++; 249 250 return i; 251 } 252 } 253 254 @property bool any() { 255 return length > 0; 256 } 257 258 @property bool isEmpty() { 259 return !any; 260 } 261 262 @property ParamCursor first() { 263 assert(any, "Cannot get the first parameter of an empty parameter list"); 264 265 foreach (c; this) 266 return c; 267 268 assert(0, "Cannot get the first parameter of an empty parameter list"); 269 } 270 } 271 272 /** Determine the set of methods that are overridden by the given 273 * method. 274 * 275 * In both Objective-C and C++, a method (aka virtual member function, 276 * in C++) can override a virtual method in a base class. For 277 * Objective-C, a method is said to override any method in the class's 278 * base class, its protocols, or its categories' protocols, that has the same 279 * selector and is of the same kind (class or instance). 280 * If no such method exists, the search continues to the class's superclass, 281 * its protocols, and its categories, and so on. A method from an Objective-C 282 * implementation is considered to override the same methods as its 283 * corresponding method in the interface. 284 * 285 * For C++, a virtual member function overrides any virtual member 286 * function with the same signature that occurs in its base 287 * classes. With multiple inheritance, a virtual member function can 288 * override several virtual member functions coming from different 289 * base classes. 290 * 291 * In all cases, this function determines the immediate overridden 292 * method, rather than all of the overridden methods. For example, if 293 * a method is originally declared in a class A, then overridden in B 294 * (which in inherits from A) and also in C (which inherited from B), 295 * then the only overridden method returned from this function when 296 * invoked on C's method will be B's method. The client may then 297 * invoke this function again, given the previously-found overridden 298 * methods, to map out the complete method-override set. 299 * 300 * \param cursor A cursor representing an Objective-C or C++ 301 * method. This routine will compute the set of methods that this 302 * method overrides. 303 * 304 * \param overridden A pointer whose pointee will be replaced with a 305 * pointer to an array of cursors, representing the set of overridden 306 * methods. If there are no overridden methods, the pointee will be 307 * set to NULL. The pointee must be freed via a call to 308 * \c clang_disposeOverriddenCursors(). 309 * 310 * \param num_overridden A pointer to the number of overridden 311 * functions, will be set to the number of overridden functions in the 312 * array pointed to by \p overridden. 313 */ 314 struct OverriddenVisitor { 315 alias Delegate = int delegate(ref Cursor); 316 317 private Cursor cursor; 318 319 this(Cursor cursor) { 320 this.cursor = cursor; 321 } 322 323 int opApply(Delegate dg) { 324 int result = 0; 325 CXCursor* overridden; 326 uint num_overridden; 327 328 clang_getOverriddenCursors(this.cursor.cx, &overridden, &num_overridden); 329 for (uint i = 0; i < num_overridden; ++overridden) { 330 auto c = Cursor(*overridden); 331 result = dg(c); 332 if (result) 333 break; 334 } 335 clang_disposeOverriddenCursors(overridden); 336 337 return result; 338 } 339 }