1 /** 2 Date: 2015-2017, Joakim Brännström 3 License: MPL-2, Mozilla Public License 2.0 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 Utilities for translation, making and generation of test doubles for functions. 7 */ 8 module cpptooling.generator.func; 9 10 import logger = std.experimental.logger; 11 12 import dsrcgen.cpp : CppModule; 13 14 import dextool.type : MainInterface; 15 import cpptooling.data : CFunction, CppClass, CppClassName, CppNsStack; 16 17 @safe: 18 19 /// Generates a C implementation calling the test double via the matching 20 /// interface. 21 void generateFuncImpl(CFunction f, CppModule impl) { 22 import cpptooling.data : joinParams, joinParamNames, toStringDecl; 23 import dsrcgen.c : E; 24 25 // assuming that a function declaration void a() in C is meant to be void 26 // a(void), not variadic. 27 string params; 28 auto p_range = f.paramRange(); 29 if (p_range.length == 1 && !f.isVariadic || p_range.length > 1) { 30 params = joinParams(p_range); 31 } 32 string names = joinParamNames(f.paramRange()); 33 34 with (impl.func_body(f.returnType.toStringDecl, f.name, params)) { 35 if (f.returnType.toStringDecl == "void") { 36 stmt(E("test_double_inst->" ~ f.name)(names)); 37 } else { 38 return_(E("test_double_inst->" ~ f.name)(names)); 39 } 40 } 41 impl.sep(2); 42 } 43 44 /** Create a C++ interface of funcs in range to allow the user to supply an 45 * implementation. 46 */ 47 CppClass makeFuncInterface(Tr)(Tr r, const CppClassName main_if) { 48 import cpptooling.data.type : CppNs; 49 50 return makeFuncInterface(r, main_if, CppNsStack(CppNs[].init)); 51 } 52 53 /** Create a C++ interface of funcs in range to allow the user to supply an 54 * implementation. 55 * 56 * Params: 57 * r = InputRange of functions the class is intended to wrap. 58 * name = the name of the class. 59 * ns = namespace the class reside in 60 */ 61 CppClass makeFuncInterface(Tr)(Tr r, const CppClassName name, const CppNsStack ns) { 62 import cpptooling.data.representation; 63 import std.array : array; 64 65 auto c = CppClass(name, CppInherit[].init, ns); 66 c.put(CppDtor(makeUniqueUSR, CppMethodName("~" ~ name), 67 CppAccess(AccessType.Public), CppVirtualMethod(MemberVirtualType.Virtual))); 68 69 foreach (f; r) { 70 auto params = f.paramRange().array(); 71 if (f.isVariadic) { 72 params = params[0 .. $ - 1]; 73 } 74 75 auto meth_name = CppMethodName(f.name); 76 auto m = CppMethod(f.usr, meth_name, params, f.returnType(), CppAccess(AccessType.Public), 77 CppConstMethod(false), CppVirtualMethod(MemberVirtualType.Pure)); 78 79 c.put(m); 80 } 81 82 return c; 83 }