1 /* 2 * Find classinfos at runtime. 3 */ 4 module qcheck.detail.runtimeclass; 5 6 package: 7 8 /** 9 * Helper that collects all classinfos from known modules for which 10 * pred returns true. 11 */ 12 ClassInfo[] findClasses(bool delegate(ClassInfo) pred) { 13 ClassInfo[] derived; 14 foreach(m; ModuleInfo) { 15 foreach(c; m.localClasses) { 16 if (pred(c)) 17 derived ~= c; 18 } 19 } 20 return derived; 21 } 22 23 24 /**************************************** 25 Predicates 26 */ 27 28 /** 29 * Returns true if base is a baseclass of derived. 30 */ 31 bool isDerived(ClassInfo derived, ClassInfo base) { 32 while (derived.base) { 33 derived = derived.base; 34 if (base is derived) 35 return true; 36 } 37 return false; 38 } 39 40 /** 41 * Returns true if derived implements the interface interf. 42 */ 43 bool implements(ClassInfo derived, ClassInfo interf) { 44 foreach(ci; derived.interfaces) { 45 if (ci.classinfo is interf) 46 return true; 47 } 48 return false; 49 } 50 51 /** 52 * Returns true if derived or any of it's base classes implements the 53 * interface interf. 54 */ 55 bool inherits(ClassInfo derived, ClassInfo interf) { 56 while (derived) { 57 if (implements(derived, interf)) 58 return true; 59 derived = derived.base; 60 } 61 return false; 62 } 63 64 65 version(unittest) { 66 class Base {} 67 class Derived : Base {} 68 interface IBase {} 69 class IImpl : IBase {} 70 class IImpl2 : IImpl {} 71 } 72 73 unittest { 74 auto classDerivatives = 75 findClasses((ClassInfo c) { return isDerived(c, Base.classinfo); } ); 76 assert(classDerivatives == [Derived.classinfo]); 77 78 auto interfaceDerivatives = 79 findClasses((ClassInfo c) { return isDerived(c, IBase.classinfo); } ); 80 assert(interfaceDerivatives.length == 0); 81 82 auto immediateImpls = 83 findClasses((ClassInfo c) { return implements(c, IBase.classinfo); } ); 84 assert(immediateImpls == [IImpl.classinfo]); 85 86 auto allInterfaceClasses = 87 findClasses((ClassInfo c) { return inherits(c, IBase.classinfo); } ); 88 assert(allInterfaceClasses == [IImpl.classinfo, IImpl2.classinfo]); 89 }