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 /// Tag an ID with a kind. 52 void tag(size_t id, Kind kind_) { 53 kind[id] = kind_; 54 } 55 56 /// Lookup the tag for an ID. 57 Kind lookup(size_t id) { 58 if (auto k = id in kind) { 59 return *k; 60 } 61 62 return Kind.none; 63 } 64 65 /// Copy an AA of classes. 66 void putForLookup(ref CppClass[FullyQualifiedNameType] other) @trusted { 67 foreach (v; other.byKeyValue) { 68 classes[v.key] = v.value; 69 } 70 } 71 72 /// Returns: a range containing the class matching fqn, if found. 73 auto lookupClass(FullyQualifiedNameType fqn) @safe { 74 import std.range : only; 75 import std.typecons : NullableRef; 76 77 typeof(only(NullableRef!CppClass())) rval; 78 if (auto c = fqn in classes) { 79 rval = only(NullableRef!CppClass(c)); 80 } 81 82 return rval; 83 } 84 } 85 86 struct IncludeHooks { 87 AbsolutePath preInclude; 88 AbsolutePath postInclude; 89 90 static auto make(T)(T transf) { 91 immutable file_cpp_pre_incl = "_pre_includes"; 92 immutable file_cpp_post_incl = "_post_includes"; 93 94 return IncludeHooks(transf.createHeaderFile(file_cpp_pre_incl), 95 transf.createHeaderFile(file_cpp_post_incl)); 96 } 97 } 98 99 struct Code { 100 enum Kind { 101 hdr, 102 impl, 103 } 104 105 CppModule cpp; 106 alias cpp this; 107 } 108 109 struct Mock { 110 // Use to generate a unique filename. 111 CppClassName name; 112 CppNs[] nesting; 113 114 CppModule cpp; 115 alias cpp this; 116 } 117 118 struct GtestPrettyPrint { 119 // Use to generate a unique filename. 120 CppClassName name; 121 CppNs[] nesting; 122 123 CppModule cpp; 124 alias cpp this; 125 } 126 127 struct GeneratedData { 128 @disable this(this); 129 130 /// Code kinds that can't be duplicated. 131 Code[Code.Kind] uniqueData; 132 133 /// All gmocks to write 134 Mock[] gmocks; 135 136 GtestPrettyPrint[] gtestPPHdr; 137 GtestPrettyPrint[] gtestPPImpl; 138 139 IncludeHooks includeHooks; 140 141 auto make(Code.Kind kind) { 142 if (auto c = kind in uniqueData) { 143 return *c; 144 } 145 146 Code m; 147 m.cpp = (new CppModule).noIndent; 148 149 uniqueData[kind] = m; 150 return m; 151 } 152 153 auto makeMock(CppNs[] ns, CppClassName name) { 154 auto m = Mock(name, ns); 155 m.cpp = (new CppModule).noIndent; 156 gmocks ~= m; 157 158 return m; 159 } 160 161 auto makeGtestPrettyPrintHdr(CppNs[] ns, CppClassName name) { 162 auto m = GtestPrettyPrint(name, ns); 163 m.cpp = (new CppModule).noIndent; 164 gtestPPHdr ~= m; 165 166 return m; 167 } 168 169 auto makeGtestPrettyPrintImpl(CppNs[] ns, CppClassName name) { 170 auto m = GtestPrettyPrint(name, ns); 171 m.cpp = (new CppModule).noIndent; 172 gtestPPImpl ~= m; 173 174 return m; 175 } 176 }