1 /** 2 Copyright: Copyright (c) 2017, Joakim Brännström. All rights reserved. 3 License: MPL-2 4 Author: Joakim Brännström (joakim.brannstrom@gmx.com) 5 6 This Source Code Form is subject to the terms of the Mozilla Public License, 7 v.2.0. If a copy of the MPL was not distributed with this file, You can obtain 8 one at http://mozilla.org/MPL/2.0/. 9 */ 10 module dextool.plugin.cpptestdouble.backend.type; 11 12 import cpptooling.data : CppRoot, CppClass, CppMethod, CppCtor, CppDtor, 13 CFunction, CppNamespace; 14 import cpptooling.data.symbol : USRType; 15 16 import dsrcgen.cpp : CppModule, noIndent; 17 18 import cpptooling.data.type : CppClassName, CppNs; 19 20 import dextool.type : AbsolutePath, FileName; 21 22 @safe: 23 24 enum Kind { 25 none, 26 /// Adapter class 27 adapter, 28 /// gmock class 29 gmock, 30 // generate a pretty print function for the class/struct 31 gtestPrettyPrint, 32 /// interface for globals 33 testDoubleNamespace, 34 testDoubleSingleton, 35 testDoubleInterface, 36 } 37 38 struct ImplData { 39 import cpptooling.data.type : CppMethodName; 40 import cpptooling.data.symbol.types : FullyQualifiedNameType; 41 42 CppRoot root; 43 44 IncludeHooks includeHooks; 45 46 /// Tagging of nodes in the root determining how they are handled by the 47 /// code generator step. 48 Kind[size_t] kind; 49 /// Classes found during src analysis. 50 CppClass[FullyQualifiedNameType] classes; 51 52 static auto make() { 53 return ImplData(CppRoot.make); 54 } 55 56 /// Tag an ID with a kind. 57 void tag(size_t id, Kind kind_) { 58 kind[id] = kind_; 59 } 60 61 /// Lookup the tag for an ID. 62 Kind lookup(size_t id) { 63 if (auto k = id in kind) { 64 return *k; 65 } 66 67 return Kind.none; 68 } 69 70 /// Copy an AA of classes. 71 void putForLookup(ref CppClass[FullyQualifiedNameType] other) @trusted { 72 foreach (v; other.byKeyValue) { 73 classes[v.key] = v.value; 74 } 75 } 76 77 /// Returns: a range containing the class matching fqn, if found. 78 auto lookupClass(FullyQualifiedNameType fqn) @safe { 79 import std.range : only; 80 import std.typecons : NullableRef; 81 82 typeof(only(NullableRef!CppClass())) rval; 83 if (auto c = fqn in classes) { 84 rval = only(NullableRef!CppClass(c)); 85 } 86 87 return rval; 88 } 89 } 90 91 struct IncludeHooks { 92 AbsolutePath preInclude; 93 AbsolutePath postInclude; 94 95 static auto make(T)(T transf) { 96 immutable file_cpp_pre_incl = "_pre_includes"; 97 immutable file_cpp_post_incl = "_post_includes"; 98 99 return IncludeHooks(transf.createHeaderFile(file_cpp_pre_incl), 100 transf.createHeaderFile(file_cpp_post_incl)); 101 } 102 } 103 104 struct Code { 105 enum Kind { 106 hdr, 107 impl, 108 } 109 110 CppModule cpp; 111 alias cpp this; 112 } 113 114 struct Mock { 115 // Use to generate a unique filename. 116 const CppClassName name; 117 const CppNs[] nesting; 118 119 CppModule cpp; 120 alias cpp this; 121 } 122 123 struct GtestPrettyPrint { 124 // Use to generate a unique filename. 125 const CppClassName name; 126 const CppNs[] nesting; 127 128 CppModule cpp; 129 alias cpp this; 130 } 131 132 struct GeneratedData { 133 @disable this(this); 134 135 /// Code kinds that can't be duplicated. 136 Code[Code.Kind] uniqueData; 137 138 /// All gmocks to write 139 Mock[] gmocks; 140 141 GtestPrettyPrint[] gtestPPHdr; 142 GtestPrettyPrint[] gtestPPImpl; 143 144 IncludeHooks includeHooks; 145 146 auto make(Code.Kind kind) { 147 if (auto c = kind in uniqueData) { 148 return *c; 149 } 150 151 Code m; 152 m.cpp = (new CppModule).noIndent; 153 154 uniqueData[kind] = m; 155 return m; 156 } 157 158 auto makeMock(const CppNs[] ns, const CppClassName name) { 159 auto m = Mock(name, ns); 160 m.cpp = (new CppModule).noIndent; 161 gmocks ~= m; 162 163 return m; 164 } 165 166 auto makeGtestPrettyPrintHdr(const CppNs[] ns, const CppClassName name) { 167 auto m = GtestPrettyPrint(name, ns); 168 m.cpp = (new CppModule).noIndent; 169 gtestPPHdr ~= m; 170 171 return m; 172 } 173 174 auto makeGtestPrettyPrintImpl(const CppNs[] ns, const CppClassName name) { 175 auto m = GtestPrettyPrint(name, ns); 176 m.cpp = (new CppModule).noIndent; 177 gtestPPImpl ~= m; 178 179 return m; 180 } 181 }