generatorbase.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * MIT License
  3. *
  4. * Copyright (c) 2019 Alexey Edelev <semlanik@gmail.com>
  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 "generatorbase.h"
  26. #include <google/protobuf/descriptor.h>
  27. #include <google/protobuf/stubs/logging.h>
  28. #include <google/protobuf/stubs/common.h>
  29. #include <google/protobuf/io/printer.h>
  30. #include <google/protobuf/io/zero_copy_stream.h>
  31. #include "utils.h"
  32. #include "templates.h"
  33. #include "generatoroptions.h"
  34. #include "generatorcommon.h"
  35. using namespace ::QtProtobuf::generator;
  36. using namespace ::google::protobuf;
  37. using namespace ::google::protobuf::compiler;
  38. GeneratorBase::GeneratorBase(Mode mode) : m_mode(mode)
  39. {
  40. }
  41. bool GeneratorBase::GenerateAll(const std::vector<const FileDescriptor *> &files, const string &parameter, GeneratorContext *generatorContext, string *error) const
  42. {
  43. return CodeGenerator::GenerateAll(files, parameter, generatorContext, error);
  44. }
  45. std::string GeneratorBase::generateBaseName(const ::google::protobuf::FileDescriptor *file, std::string name)
  46. {
  47. std::vector<std::string> packages = utils::split(file->package(), '.');
  48. std::string outFileBasename = "";
  49. if (GeneratorOptions::instance().isFolder()) {
  50. for (auto package : packages) {
  51. outFileBasename += package + "/";
  52. }
  53. outFileBasename += name;
  54. } else {
  55. outFileBasename = name;
  56. }
  57. return outFileBasename;
  58. }
  59. void GeneratorBase::printDisclaimer(const std::shared_ptr<::google::protobuf::io::Printer> printer)
  60. {
  61. printer->Print(Templates::DisclaimerTemplate);
  62. }
  63. void GeneratorBase::printPreamble(const std::shared_ptr<::google::protobuf::io::Printer> printer)
  64. {
  65. printer->Print(Templates::PreambleTemplate);
  66. }
  67. void GeneratorBase::printInclude(const std::shared_ptr<::google::protobuf::io::Printer> printer, const google::protobuf::Descriptor *message, const FieldDescriptor *field, std::set<std::string> &existingIncludes)
  68. {
  69. assert(field != nullptr);
  70. std::string newInclude;
  71. const char *includeTemplate = "";
  72. switch (field->type()) {
  73. case FieldDescriptor::TYPE_MESSAGE:
  74. if (field->is_map()) {
  75. newInclude = "QMap";
  76. assert(field->message_type() != nullptr);
  77. assert(field->message_type()->field_count() == 2);
  78. printInclude(printer, message, field->message_type()->field(0), existingIncludes);
  79. printInclude(printer, message, field->message_type()->field(1), existingIncludes);
  80. includeTemplate = Templates::ExternalIncludeTemplate;
  81. } else if (common::isQtType(field)) {
  82. newInclude = field->message_type()->name();
  83. includeTemplate = Templates::ExternalIncludeTemplate;
  84. } else {
  85. if (!common::isNested(field->message_type())) {
  86. std::string outFileBasename = "";
  87. std::string fieldPackage = field->message_type()->file()->package();
  88. if (fieldPackage != message->file()->package()) {
  89. std::vector<std::string> packages = utils::split(fieldPackage, '.');
  90. for (auto package : packages) {
  91. outFileBasename += package + "/";
  92. }
  93. }
  94. std::string typeName = field->message_type()->name();
  95. utils::tolower(typeName);
  96. newInclude = outFileBasename + typeName;
  97. includeTemplate = Templates::InternalIncludeTemplate;
  98. } else if (!common::isNestedOf(field->message_type(), message)) {
  99. auto containingMessage = common::findHighestMessage(field->message_type());
  100. if (containingMessage != message) {
  101. std::string outFileBasename = "";
  102. std::string fieldPackage = containingMessage->file()->package();
  103. if (fieldPackage != message->file()->package()) {
  104. std::vector<std::string> packages = utils::split(fieldPackage, '.');
  105. for (auto package : packages) {
  106. outFileBasename += package + "/";
  107. }
  108. }
  109. std::string typeName = containingMessage->name();
  110. utils::tolower(typeName);
  111. newInclude = outFileBasename + typeName;
  112. includeTemplate = Templates::InternalIncludeTemplate;
  113. }
  114. }
  115. }
  116. break;
  117. case FieldDescriptor::TYPE_BYTES:
  118. newInclude = "QByteArray";
  119. includeTemplate = Templates::ExternalIncludeTemplate;
  120. break;
  121. case FieldDescriptor::TYPE_STRING:
  122. newInclude = "QString";
  123. includeTemplate = Templates::ExternalIncludeTemplate;
  124. break;
  125. case FieldDescriptor::TYPE_ENUM: {
  126. common::EnumVisibility enumVisibily = common::enumVisibility(field->enum_type(), message);
  127. if (enumVisibily == common::GLOBAL_ENUM) {
  128. includeTemplate = Templates::GlobalEnumIncludeTemplate;
  129. } else if (enumVisibily == common::NEIGHBOR_ENUM) {
  130. includeTemplate = Templates::InternalIncludeTemplate;
  131. std::string fullEnumName = field->enum_type()->full_name();
  132. std::vector<std::string> fullEnumNameParts = utils::split(fullEnumName, '.');
  133. std::string enumTypeOwner = fullEnumNameParts.at(fullEnumNameParts.size() - 2);
  134. utils::tolower(enumTypeOwner);
  135. newInclude = enumTypeOwner;
  136. } else {
  137. return;
  138. }
  139. }
  140. break;
  141. default:
  142. return;
  143. }
  144. if (existingIncludes.find(newInclude) == std::end(existingIncludes)) {
  145. printer->Print({{"include", newInclude}}, includeTemplate);
  146. existingIncludes.insert(newInclude);
  147. }
  148. }
  149. void GeneratorBase::printQtProtobufUsingNamespace(const std::shared_ptr<::google::protobuf::io::Printer> printer)
  150. {
  151. printer->Print({{"namespace", "QtProtobuf"}}, Templates::UsingNamespaceTemplate);
  152. }
  153. void GeneratorBase::printNamespaces(const std::shared_ptr<::google::protobuf::io::Printer> printer, const std::vector<std::string> namespaces) {
  154. printer->Print("\n");
  155. for (auto ns : namespaces) {
  156. printer->Print({{"namespace", ns}}, Templates::NamespaceTemplate);
  157. }
  158. }