generator.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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 "generator.h"
  26. #include "templates.h"
  27. #include "classgeneratorbase.h"
  28. #include <google/protobuf/stubs/logging.h>
  29. #include <google/protobuf/stubs/common.h>
  30. #include <google/protobuf/io/printer.h>
  31. #include <google/protobuf/io/zero_copy_stream.h>
  32. #include <google/protobuf/descriptor.h>
  33. #include <algorithm>
  34. #include <unordered_map>
  35. #include <vector>
  36. #include <sstream>
  37. #include <string>
  38. using namespace ::google::protobuf;
  39. using namespace ::google::protobuf::compiler;
  40. using namespace qtprotobuf;
  41. class QtClassGenerator : public ClassGeneratorBase
  42. {
  43. std::string mPackage;
  44. const Descriptor* mMessage;
  45. std::set<std::string> mExtractedModels;
  46. public:
  47. QtClassGenerator(const std::string& package, const Descriptor* message, std::unique_ptr<io::ZeroCopyOutputStream> out) :
  48. ClassGeneratorBase(message->name(), std::move(out))
  49. , mPackage(std::move(package))
  50. , mMessage(message){}
  51. void run() {
  52. //Post generation collect all generated model types
  53. for (int i = 0; i < mMessage->field_count(); i++) {
  54. const FieldDescriptor* field = mMessage->field(i);
  55. if (field->is_repeated()
  56. && field->type() == FieldDescriptor::TYPE_MESSAGE) {
  57. std::string typeName = field->message_type()->name();
  58. mExtractedModels.insert(typeName);
  59. }
  60. }
  61. printPreamble();
  62. printIncludes(mMessage);
  63. if (mExtractedModels.size() > 0) {
  64. mPrinter.Print("\n#include <universallistmodel.h>\n");
  65. }
  66. printNamespaces(mPackage);
  67. printClass();
  68. printProperties(mMessage);
  69. enclose();
  70. }
  71. const std::set<std::string>& extractedModels() const {
  72. return mExtractedModels;
  73. }
  74. };
  75. class GlobalEnumsGenerator : public ClassGeneratorBase
  76. {
  77. const FileDescriptor* mFile;
  78. public:
  79. GlobalEnumsGenerator(const FileDescriptor* file, std::unique_ptr<io::ZeroCopyOutputStream> out) :
  80. ClassGeneratorBase("GlobalEnums", std::move(out))
  81. , mFile(file)
  82. {}
  83. void run() {
  84. printPreamble();
  85. printNamespaces(mFile->package());
  86. printClass();
  87. printQEnums<FileDescriptor>(mFile);
  88. enclose();
  89. }
  90. };
  91. bool QtGenerator::Generate(const FileDescriptor* file,
  92. const std::string& /*parameter*/,
  93. GeneratorContext* generator_context,
  94. std::string* error) const
  95. {
  96. if (file->syntax() != FileDescriptor::SYNTAX_PROTO3) {
  97. *error = "Invalid proto used. This plugin only supports 'proto3' syntax";
  98. return false;
  99. }
  100. std::set<std::string> extractedModels;
  101. for(int i = 0; i < file->message_type_count(); i++) {
  102. const Descriptor* message = file->message_type(i);
  103. std::string filename = message->name() + ".h";
  104. std::transform(std::begin(filename), std::end(filename), std::begin(filename), ::tolower);
  105. QtClassGenerator classGen(file->package(), message,
  106. std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generator_context->Open(filename))));
  107. classGen.run();
  108. extractedModels.insert(std::begin(classGen.extractedModels()), std::end(classGen.extractedModels()));
  109. }
  110. std::string globalEnumsFilename = "globalenums.h";
  111. GlobalEnumsGenerator enumGen(file, std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generator_context->Open(globalEnumsFilename))));
  112. enumGen.run();
  113. //TODO: move to separate class also slipt definitions
  114. //Print list models
  115. std::unique_ptr<io::ZeroCopyOutputStream> out(generator_context->Open("listmodels.h"));
  116. io::Printer printer(out.get(), '$');
  117. printer.Print(PreambleTemplate);
  118. for(auto modelTypeName : extractedModels) {
  119. std::string modelTypeNameLower(modelTypeName);
  120. std::transform(std::begin(modelTypeNameLower), std::end(modelTypeNameLower), std::begin(modelTypeNameLower), ::tolower);
  121. printer.Print({{"type_lower", modelTypeNameLower}}, InternalIncludeTemplate);
  122. }
  123. printer.Print("\n#include <universallistmodel.h>\n");
  124. for(auto modelTypeName : extractedModels) {
  125. printer.Print({{"type", modelTypeName}}, ModelClassTemplate);
  126. }
  127. return true;
  128. }