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 private: 177 178 } 179 180 struct DeclarationVisitor { 181 mixin Visitor.Constructors; 182 183 int opApply(Visitor.Delegate dg) { 184 foreach (cursor, parent; visitor) { 185 if (cursor.isDeclaration) { 186 if (auto result = dg(cursor, parent)) { 187 return result; 188 } 189 } 190 } 191 192 return 0; 193 } 194 } 195 196 struct TypedVisitor(CXCursorKind kind) { 197 private Visitor visitor; 198 199 this(Visitor visitor) { 200 this.visitor = visitor; 201 } 202 203 this(Cursor cursor) { 204 this.visitor = Visitor(cursor); 205 } 206 207 int opApply(Visitor.Delegate dg) { 208 foreach (cursor, parent; visitor) { 209 if (cursor.kind == kind) { 210 if (auto result = dg(cursor, parent)) { 211 return result; 212 } 213 } 214 } 215 216 return 0; 217 } 218 } 219 220 alias ObjCInstanceMethodVisitor = TypedVisitor!(CXCursorKind.objCInstanceMethodDecl); 221 alias ObjCClassMethodVisitor = TypedVisitor!(CXCursorKind.objCClassMethodDecl); 222 alias ObjCPropertyVisitor = TypedVisitor!(CXCursorKind.objCPropertyDecl); 223 alias ObjCProtocolVisitor = TypedVisitor!(CXCursorKind.objCProtocolRef); 224 225 struct ParamVisitor { 226 mixin Visitor.Constructors; 227 228 int opApply(int delegate(ref ParamCursor) dg) { 229 foreach (cursor, parent; visitor) { 230 if (cursor.kind == CXCursorKind.parmDecl) { 231 auto paramCursor = ParamCursor(cursor); 232 233 if (auto result = dg(paramCursor)) 234 return result; 235 } 236 } 237 238 return 0; 239 } 240 241 @property size_t length() { 242 auto type = Cursor(visitor.cursor).type; 243 244 if (type.isValid) 245 return type.func.arguments.length; 246 247 else { 248 size_t i; 249 250 foreach (_; this) 251 i++; 252 253 return i; 254 } 255 } 256 257 @property bool any() { 258 return length > 0; 259 } 260 261 @property bool isEmpty() { 262 return !any; 263 } 264 265 @property ParamCursor first() { 266 assert(any, "Cannot get the first parameter of an empty parameter list"); 267 268 foreach (c; this) 269 return c; 270 271 assert(0, "Cannot get the first parameter of an empty parameter list"); 272 } 273 } 274 275 /** Determine the set of methods that are overridden by the given 276 * method. 277 * 278 * In both Objective-C and C++, a method (aka virtual member function, 279 * in C++) can override a virtual method in a base class. For 280 * Objective-C, a method is said to override any method in the class's 281 * base class, its protocols, or its categories' protocols, that has the same 282 * selector and is of the same kind (class or instance). 283 * If no such method exists, the search continues to the class's superclass, 284 * its protocols, and its categories, and so on. A method from an Objective-C 285 * implementation is considered to override the same methods as its 286 * corresponding method in the interface. 287 * 288 * For C++, a virtual member function overrides any virtual member 289 * function with the same signature that occurs in its base 290 * classes. With multiple inheritance, a virtual member function can 291 * override several virtual member functions coming from different 292 * base classes. 293 * 294 * In all cases, this function determines the immediate overridden 295 * method, rather than all of the overridden methods. For example, if 296 * a method is originally declared in a class A, then overridden in B 297 * (which in inherits from A) and also in C (which inherited from B), 298 * then the only overridden method returned from this function when 299 * invoked on C's method will be B's method. The client may then 300 * invoke this function again, given the previously-found overridden 301 * methods, to map out the complete method-override set. 302 * 303 * \param cursor A cursor representing an Objective-C or C++ 304 * method. This routine will compute the set of methods that this 305 * method overrides. 306 * 307 * \param overridden A pointer whose pointee will be replaced with a 308 * pointer to an array of cursors, representing the set of overridden 309 * methods. If there are no overridden methods, the pointee will be 310 * set to NULL. The pointee must be freed via a call to 311 * \c clang_disposeOverriddenCursors(). 312 * 313 * \param num_overridden A pointer to the number of overridden 314 * functions, will be set to the number of overridden functions in the 315 * array pointed to by \p overridden. 316 */ 317 struct OverriddenVisitor { 318 alias Delegate = int delegate(ref Cursor); 319 320 private Cursor cursor; 321 322 this(Cursor cursor) { 323 this.cursor = cursor; 324 } 325 326 int opApply(Delegate dg) { 327 int result = 0; 328 CXCursor* overridden; 329 uint num_overridden; 330 331 clang_getOverriddenCursors(this.cursor.cx, &overridden, &num_overridden); 332 for (uint i = 0; i < num_overridden; ++overridden) { 333 auto c = Cursor(*overridden); 334 result = dg(c); 335 if (result) 336 break; 337 } 338 clang_disposeOverriddenCursors(overridden); 339 340 return result; 341 } 342 }