protobufsourcegenerator.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. * MIT License
  3. *
  4. * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>, Tatyana Borisova <tanusshhka@mail.ru>
  5. *
  6. * This file is part of QtProtobuf project https://git.semlanik.org/semlanik/qtprotobuf
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy of this
  9. * software and associated documentation files (the "Software"), to deal in the Software
  10. * without restriction, including without limitation the rights to use, copy, modify,
  11. * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
  12. * to permit persons to whom the Software is furnished to do so, subject to the following
  13. * conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in all copies
  16. * or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
  19. * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  20. * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
  21. * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
  22. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. * DEALINGS IN THE SOFTWARE.
  24. */
  25. #include "protobufsourcegenerator.h"
  26. #include "utils.h"
  27. #include <google/protobuf/descriptor.h>
  28. #include <google/protobuf/io/zero_copy_stream.h>
  29. #include "generatoroptions.h"
  30. using namespace QtProtobuf::generator;
  31. using namespace ::google::protobuf;
  32. using namespace ::google::protobuf::io;
  33. using namespace ::google::protobuf::compiler;
  34. ProtobufSourceGenerator::ProtobufSourceGenerator(const google::protobuf::Descriptor *message,
  35. const std::shared_ptr<google::protobuf::io::ZeroCopyOutputStream> &out) :
  36. ClassSourceGeneratorBase(message->full_name(), out)
  37. , mMessage(message)
  38. {
  39. }
  40. ProtobufSourceGenerator::ProtobufSourceGenerator(const google::protobuf::Descriptor *message, const std::shared_ptr<::google::protobuf::io::Printer> &printer) :
  41. ClassSourceGeneratorBase(message->full_name(), printer)
  42. , mMessage(message)
  43. {
  44. }
  45. void ProtobufSourceGenerator::printRegisterBody()
  46. {
  47. const std::map<std::string, std::string> registrationProperties = {{"classname", mClassName},
  48. {"namespaces", mNamespacesColonDelimited},
  49. {"package", mMessage->file()->package()}
  50. };
  51. mPrinter->Print(registrationProperties,
  52. Templates::ManualRegistrationComplexTypeDefinition);
  53. Indent();
  54. if (GeneratorOptions::instance().hasQml()) {
  55. mPrinter->Print(registrationProperties, Templates::RegisterQmlListPropertyMetaTypeTemplate);
  56. mPrinter->Print(registrationProperties, Templates::QmlRegisterTypeTemplate);
  57. }
  58. for (int i = 0; i < mMessage->field_count(); i++) {
  59. const FieldDescriptor *field = mMessage->field(i);
  60. if (field->type() == FieldDescriptor::TYPE_ENUM
  61. && isLocalMessageEnum(mMessage, field)) {
  62. mPrinter->Print({{"type", mClassName + "::" + field->enum_type()->name() + Templates::ListSuffix},
  63. {"namespaces", mNamespacesColonDelimited}},
  64. Templates::RegisterMetaTypeTemplateNoNamespace);
  65. mPrinter->Print({{"type", mClassName + "::" + field->enum_type()->name() + Templates::ListSuffix},
  66. {"namespaces", mNamespacesColonDelimited}},
  67. Templates::RegisterMetaTypeTemplate);
  68. mPrinter->Print({{"type", mClassName + "::" + field->enum_type()->name()},
  69. {"namespaces", mNamespacesColonDelimited}},
  70. Templates::RegisterMetaTypeTemplateNoNamespace);
  71. mPrinter->Print({{"type", mClassName + "::" + field->enum_type()->name()},
  72. {"namespaces", mNamespacesColonDelimited}},
  73. Templates::RegisterMetaTypeTemplate);
  74. mPrinter->Print({{"type", mClassName + "::" + field->enum_type()->name()}},
  75. Templates::RegisterEnumSerializersTemplate);
  76. } else if (field->is_map()) {
  77. mPrinter->Print({{"type", field->message_type()->name()},
  78. {"namespaces", mClassName}},
  79. Templates::RegisterMetaTypeTemplate);
  80. mPrinter->Print({{"type", field->message_type()->name()},
  81. {"namespaces", mNamespacesColonDelimited + "::" + mClassName}},
  82. Templates::RegisterMetaTypeTemplate);
  83. mPrinter->Print({{"classname", mClassName},
  84. {"type", field->message_type()->name()},
  85. {"key_type", getTypeName(field->message_type()->field(0), mMessage)},
  86. {"value_type", getTypeName(field->message_type()->field(1), mMessage)}},
  87. Templates::MapSerializationRegisterTemplate);
  88. }
  89. }
  90. Outdent();
  91. mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
  92. }
  93. void ProtobufSourceGenerator::printFieldsOrdering() {
  94. mPrinter->Print({{"type", mClassName}}, Templates::FieldsOrderingContainerTemplate);
  95. Indent();
  96. for (int i = 0; i < mMessage->field_count(); i++) {
  97. const FieldDescriptor *field = mMessage->field(i);
  98. if (i != 0) {
  99. mPrinter->Print("\n,");
  100. }
  101. //property_number is incremented by 1 because user properties stating from 1.
  102. //Property with index 0 is "objectName"
  103. mPrinter->Print({{"field_number", std::to_string(field->number())},
  104. {"property_number", std::to_string(i + 1)}}, Templates::FieldOrderTemplate);
  105. }
  106. Outdent();
  107. mPrinter->Print(Templates::SemicolonBlockEnclosureTemplate);
  108. mPrinter->Print("\n");
  109. }
  110. void ProtobufSourceGenerator::printConstructor()
  111. {
  112. std::vector<std::string> parameterList;
  113. for (int i = 0; i < mMessage->field_count(); i++) {
  114. const FieldDescriptor *field = mMessage->field(i);
  115. std::string fieldTypeName = getTypeName(field, mMessage);
  116. std::string fieldName = utils::lowerCaseName(field->name());
  117. fieldName = qualifiedName(fieldName);
  118. if (field->is_repeated() || field->is_map()) {
  119. parameterList.push_back("const " + fieldTypeName + " &" + fieldName);
  120. } else {
  121. switch (field->type()) {
  122. case FieldDescriptor::TYPE_DOUBLE:
  123. case FieldDescriptor::TYPE_FLOAT:
  124. parameterList.push_back(fieldTypeName + " " + fieldName);
  125. break;
  126. case FieldDescriptor::TYPE_FIXED32:
  127. case FieldDescriptor::TYPE_FIXED64:
  128. case FieldDescriptor::TYPE_INT32:
  129. case FieldDescriptor::TYPE_INT64:
  130. case FieldDescriptor::TYPE_SINT32:
  131. case FieldDescriptor::TYPE_SINT64:
  132. case FieldDescriptor::TYPE_UINT32:
  133. case FieldDescriptor::TYPE_UINT64:
  134. parameterList.push_back(fieldTypeName + " " + fieldName);
  135. break;
  136. case FieldDescriptor::TYPE_BOOL:
  137. parameterList.push_back(fieldTypeName + " " + fieldName);
  138. break;
  139. case FieldDescriptor::TYPE_BYTES:
  140. case FieldDescriptor::TYPE_STRING:
  141. case FieldDescriptor::TYPE_MESSAGE:
  142. parameterList.push_back("const " + fieldTypeName + " &" + fieldName);
  143. break;
  144. default:
  145. parameterList.push_back(fieldTypeName + " " + fieldName);
  146. break;
  147. }
  148. }
  149. }
  150. for (size_t i = 0; i <= parameterList.size(); i++) {
  151. std::string parameters = "";
  152. for (size_t j = 0; j < i; j++) {
  153. parameters += parameterList[j] + ", ";
  154. }
  155. mPrinter->Print({{"classname", mClassName},
  156. {"parameter_list", parameters}}, Templates::ProtoConstructorDefinitionTemplate);
  157. for (size_t j = 0; j < parameterList.size(); j++) {
  158. const FieldDescriptor *field = mMessage->field(j);
  159. std::string fieldName = utils::lowerCaseName(field->name());
  160. auto fieldTypeName = getTypeName(field, mMessage);
  161. fieldName = qualifiedName(fieldName);
  162. if (field->type() == FieldDescriptor::TYPE_MESSAGE
  163. && !field->is_map() && !field->is_repeated()) {
  164. if (j < i) {
  165. mPrinter->Print({{"property_name", fieldName}, {"type", fieldTypeName}}, Templates::MessagePropertyInitializerTemplate);
  166. } else {
  167. mPrinter->Print({{"property_name", fieldName}, {"type", fieldTypeName}}, Templates::MessagePropertyEmptyInitializerTemplate);
  168. }
  169. } else {
  170. if (j < i) {
  171. mPrinter->Print({{"property_name", fieldName}}, Templates::PropertyInitializerTemplate);
  172. } else {
  173. std::string initializer = "";
  174. if (!field->is_repeated() && !field->is_map()) {
  175. switch (field->type()) {
  176. case FieldDescriptor::TYPE_DOUBLE:
  177. case FieldDescriptor::TYPE_FLOAT:
  178. initializer = "0.0";
  179. break;
  180. case FieldDescriptor::TYPE_FIXED32:
  181. case FieldDescriptor::TYPE_FIXED64:
  182. case FieldDescriptor::TYPE_INT32:
  183. case FieldDescriptor::TYPE_INT64:
  184. case FieldDescriptor::TYPE_SINT32:
  185. case FieldDescriptor::TYPE_SINT64:
  186. case FieldDescriptor::TYPE_UINT32:
  187. case FieldDescriptor::TYPE_UINT64:
  188. initializer = "0";
  189. break;
  190. case FieldDescriptor::TYPE_BOOL:
  191. initializer = "false";
  192. break;
  193. case FieldDescriptor::TYPE_ENUM:
  194. initializer = fieldTypeName + "::" + field->enum_type()->value(0)->name();
  195. break;
  196. default:
  197. break;
  198. }
  199. }
  200. if (initializer != "") {
  201. mPrinter->Print({{"property_name", fieldName}, {"initializer", initializer}}, Templates::PropertyEmptyInitializerTemplate);
  202. }
  203. }
  204. }
  205. }
  206. mPrinter->Print(Templates::ConstructorContentTemplate);
  207. mPrinter->Print("\n");
  208. }
  209. }
  210. void ProtobufSourceGenerator::printCopyFunctionality()
  211. {
  212. mPrinter->Print({{"classname", mClassName}},
  213. Templates::CopyConstructorDefinitionTemplate);
  214. for (int j = 0; j < mMessage->field_count(); j++) {
  215. const FieldDescriptor *field = mMessage->field(j);
  216. std::string fieldName = utils::lowerCaseName(field->name());
  217. auto fieldTypeName = getTypeName(field, mMessage);
  218. fieldName = qualifiedName(fieldName);
  219. if (field->type() == FieldDescriptor::TYPE_MESSAGE
  220. && !field->is_map() && !field->is_repeated()) {
  221. mPrinter->Print({{"property_name", fieldName}, {"type", fieldTypeName}}, Templates::MessagePropertyEmptyInitializerTemplate);
  222. }
  223. }
  224. mPrinter->Print("\n{\n");
  225. Indent();
  226. for (int i = 0; i < mMessage->field_count(); i++) {
  227. auto field = mMessage->field(i);
  228. if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
  229. printField(mMessage, field, Templates::CopyComplexFieldTemplate);
  230. } else {
  231. printField(mMessage, field, Templates::CopyFieldTemplate);
  232. }
  233. }
  234. Outdent();
  235. mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
  236. mPrinter->Print({{"classname", mClassName}},
  237. Templates::AssignmentOperatorDefinitionTemplate);
  238. Indent();
  239. for (int i = 0; i < mMessage->field_count(); i++) {
  240. auto field = mMessage->field(i);
  241. if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
  242. printField(mMessage, field, Templates::CopyComplexFieldTemplate);
  243. } else {
  244. printField(mMessage, field, Templates::CopyFieldTemplate);
  245. }
  246. }
  247. mPrinter->Print(Templates::AssignmentOperatorReturnTemplate);
  248. Outdent();
  249. mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
  250. }
  251. void ProtobufSourceGenerator::printMoveSemantic()
  252. {
  253. assert(mMessage != nullptr);
  254. mPrinter->Print({{"classname", mClassName}},
  255. Templates::MoveConstructorDefinitionTemplate);
  256. for (int j = 0; j < mMessage->field_count(); j++) {
  257. const FieldDescriptor *field = mMessage->field(j);
  258. std::string fieldName = utils::lowerCaseName(field->name());
  259. auto fieldTypeName = getTypeName(field, mMessage);
  260. fieldName = qualifiedName(fieldName);
  261. if (field->type() == FieldDescriptor::TYPE_MESSAGE
  262. && !field->is_map() && !field->is_repeated()) {
  263. mPrinter->Print({{"property_name", fieldName}, {"type", fieldTypeName}}, Templates::MessagePropertyEmptyInitializerTemplate);
  264. }
  265. }
  266. mPrinter->Print("\n{\n");
  267. Indent();
  268. for (int i = 0; i < mMessage->field_count(); i++) {
  269. const FieldDescriptor *field = mMessage->field(i);
  270. if (isComplexType(field) || field->is_repeated()) {
  271. if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
  272. printField(mMessage, field, Templates::MoveMessageFieldTemplate);
  273. } else {
  274. printField(mMessage, field, Templates::MoveComplexFieldConstructorTemplate);
  275. }
  276. } else {
  277. if (field->type() != FieldDescriptor::TYPE_ENUM) {
  278. printField(mMessage, field, Templates::MoveFieldTemplate);
  279. }
  280. else {
  281. printField(mMessage, field, Templates::EnumMoveFieldTemplate);
  282. }
  283. }
  284. }
  285. Outdent();
  286. mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
  287. mPrinter->Print({{"classname", mClassName}},
  288. Templates::MoveAssignmentOperatorDefinitionTemplate);
  289. Indent();
  290. for (int i = 0; i < mMessage->field_count(); i++) {
  291. const FieldDescriptor *field = mMessage->field(i);
  292. if (isComplexType(field) || field->is_repeated()) {
  293. if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
  294. printField(mMessage, field, Templates::MoveMessageFieldTemplate);
  295. } else {
  296. printField(mMessage, field, Templates::MoveComplexFieldTemplate);
  297. }
  298. } else {
  299. if (field->type() != FieldDescriptor::TYPE_ENUM) {
  300. printField(mMessage, field, Templates::MoveFieldTemplate);
  301. }
  302. else {
  303. printField(mMessage, field, Templates::EnumMoveFieldTemplate);
  304. }
  305. }
  306. }
  307. mPrinter->Print(Templates::AssignmentOperatorReturnTemplate);
  308. Outdent();
  309. mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
  310. }
  311. void ProtobufSourceGenerator::printComparisonOperators()
  312. {
  313. assert(mMessage != nullptr);
  314. PropertyMap properties;
  315. mPrinter->Print({{"classname", mClassName}}, Templates::EqualOperatorDefinitionTemplate);
  316. bool isFirst = true;
  317. if (mMessage->field_count() <= 0) {
  318. mPrinter->Print("true");
  319. }
  320. for (int i = 0; i < mMessage->field_count(); i++) {
  321. const FieldDescriptor *field = mMessage->field(i);
  322. if (producePropertyMap(mMessage, field, properties)) {
  323. if (!isFirst) {
  324. mPrinter->Print("\n&& ");
  325. } else {
  326. Indent();
  327. Indent();
  328. isFirst = false;
  329. }
  330. if (field->type() == FieldDescriptor::TYPE_MESSAGE
  331. && !field->is_map() && !field->is_repeated()) {
  332. mPrinter->Print(properties, Templates::EqualOperatorMessagePropertyTemplate);
  333. } else {
  334. mPrinter->Print(properties, Templates::EqualOperatorPropertyTemplate);
  335. }
  336. }
  337. }
  338. //Only if at least one field "copied"
  339. if (!isFirst) {
  340. Outdent();
  341. Outdent();
  342. }
  343. mPrinter->Print(";\n");
  344. mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
  345. mPrinter->Print({{"classname", mClassName}}, Templates::NotEqualOperatorDefinitionTemplate);
  346. }
  347. void ProtobufSourceGenerator::printGetters()
  348. {
  349. for (int i = 0; i < mMessage->field_count(); i++) {
  350. const FieldDescriptor *field = mMessage->field(i);
  351. if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
  352. printField(mMessage, field, Templates::GetterPrivateMessageDefinitionTemplate);
  353. printField(mMessage, field, Templates::GetterMessageDefinitionTemplate);
  354. }
  355. if (field->is_repeated()) {
  356. printField(mMessage, field, Templates::GetterContainerExtraDefinitionTemplate);
  357. if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map()
  358. && GeneratorOptions::instance().hasQml()) {
  359. printField(mMessage, field, Templates::GetterQmlListDefinitionTemplate);
  360. }
  361. }
  362. }
  363. for (int i = 0; i < mMessage->field_count(); i++) {
  364. auto field = mMessage->field(i);
  365. switch (field->type()) {
  366. case FieldDescriptor::TYPE_MESSAGE:
  367. if (!field->is_map() && !field->is_repeated()) {
  368. printField(mMessage, field, Templates::SetterPrivateTemplateDefinitionMessageType);
  369. printField(mMessage, field, Templates::SetterTemplateDefinitionMessageType);
  370. } else {
  371. printField(mMessage, field, Templates::SetterTemplateDefinitionComplexType);
  372. }
  373. break;
  374. case FieldDescriptor::FieldDescriptor::TYPE_STRING:
  375. case FieldDescriptor::FieldDescriptor::TYPE_BYTES:
  376. printField(mMessage, field, Templates::SetterTemplateDefinitionComplexType);
  377. break;
  378. default:
  379. break;
  380. }
  381. }
  382. }
  383. void ProtobufSourceGenerator::printDestructor()
  384. {
  385. mPrinter->Print({{"classname", mClassName}}, "$classname$::~$classname$()\n"
  386. "{}\n\n");
  387. }
  388. void ProtobufSourceGenerator::printIncludes()
  389. {
  390. std::set<std::string> existingIncludes;
  391. for (int i = 0; i < mMessage->field_count(); i++) {
  392. printInclude(mMessage, mMessage->field(i), existingIncludes);
  393. }
  394. }