1 module dmocks.method_mock; 2 3 import dmocks.qualifiers; 4 import dmocks.repository; 5 import std.conv; 6 import std.traits; 7 8 package: 9 10 //These are too complicated for decent unittests. Can't mock templates! 11 12 /++ 13 The only method we care about externally. 14 Returns a string containing the overrides for this method 15 and all its overloads. 16 ++/ 17 string Methods (T, bool INHERITANCE, string methodName) () { 18 string methodBodies = ""; 19 20 static if (is (typeof(__traits(getOverloads, T, methodName)))) 21 { 22 foreach (overloadIndex, method; __traits(getOverloads, T, methodName)) 23 { 24 static if (!__traits(isStaticFunction, method) && !(methodName[0..2] == "__") && 25 !(INHERITANCE && __traits(isFinalFunction, method))) 26 methodBodies ~= BuildMethodOverloads!(T.stringof, methodName, overloadIndex, method, INHERITANCE); 27 } 28 } 29 return methodBodies; 30 } 31 32 /++ 33 Returns a string containing the overload for a single function. 34 This function has a return value. 35 ++/ 36 string BuildMethodOverloads (string objectType, string methodName, int overloadIndex, alias method, bool inheritance)() 37 { 38 alias FunctionTypeOf!(method) METHOD_TYPE; 39 enum returns = !is (ReturnType!(METHOD_TYPE) == void); 40 41 enum self = `__traits(getOverloads, T, "` ~ methodName ~ `")[` ~ overloadIndex.to!string ~ `]`; 42 enum selfType = "FunctionTypeOf!("~self~")"; 43 enum ret = returns ? `ReturnType!(` ~ selfType ~ `)` : `void`; 44 enum paramTypes = `ParameterTypeTuple!(` ~ selfType ~ `)`; 45 enum dynVarArgs = variadicFunctionStyle!method == Variadic.d; 46 enum varargsString = dynVarArgs ? ", ..." : ""; 47 enum qualified = objectType ~ `.` ~ methodName; 48 enum bool override_ = is(typeof(mixin (`Object.` ~ methodName))) && !__traits(isFinalFunction, method); 49 enum header = ((inheritance || override_) ? `override ` : `final `) ~ ret ~ ` ` ~ methodName ~ ` 50 (` ~ paramTypes ~ ` params`~ varargsString ~`) ` ~ formatQualifiers!(method); 51 52 string delegate_ = `delegate `~ret~` (`~paramTypes~` args, TypeInfo[] varArgsList, void* varArgsPtr){ ` ~ BuildForwardCall!(methodName, dynVarArgs) ~ `}`; 53 54 enum varargsValueString = dynVarArgs ? ", _arguments, _argptr" : ", null, null"; 55 return header ~` { return mockMethodCall!(`~self~`, "`~methodName~`", T)(this, _owner, ` ~ delegate_ ~ varargsValueString ~`, params); `~`} `; 56 } 57 58 string BuildForwardCall(string methodName, bool dynamicVarArgs)() 59 { 60 enum methodString = dynamicVarArgs ? "v"~methodName : methodName; 61 enum argsPassed = dynamicVarArgs ? "(args, varArgsList, varArgsPtr)" : "(args)"; 62 63 return `static if (is (typeof (mocked___.` ~ methodString~`))) 64 { 65 return (mocked___.` ~ methodString ~ argsPassed~`); 66 } 67 else static if (is (typeof (super.` ~ methodString~`))) 68 { 69 return (super.` ~ methodString ~ argsPassed~`); 70 } 71 else 72 { 73 assert(false, "Cannot pass the call through - there's no `~methodString~` implementation in base object!"); 74 }`; 75 }