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