Browse Source

Combine global enums from multiple .proto

- Combine global enums from all .proto files
- Update tests
- Change Q_ENUMS to Q_ENUM

Note: Qt 5.4 and less seems not supported after this commit
Alexey Edelev 6 years ago
parent
commit
2938e76d07

+ 2 - 2
CMakeLists.txt

@@ -36,14 +36,14 @@ if ($ENV{MAKE_TESTS})
         include_directories("src/lib")
         add_custom_command(TARGET ${testgeneration} POST_BUILD
             COMMAND ${PROTOBUF_INSTALATION_PATH}/bin/protoc.exe --plugin=protoc-gen-${PROJECT_NAME}=${CMAKE_BINARY_DIR}/qtprotobuf.exe --qtprotobuf_out=${CMAKE_CURRENT_BINARY_DIR}/tests
-            simpletest.proto
+            *.proto
             WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests/proto/
             COMMENT "Generating test headers"
             )
     elseif (UNIX)
         add_custom_command(TARGET ${testgeneration} POST_BUILD
             COMMAND protoc --plugin=protoc-gen-${PROJECT_NAME}=${CMAKE_BINARY_DIR}/qtprotobuf --qtprotobuf_out=${CMAKE_CURRENT_BINARY_DIR}/tests
-            simpletest.proto
+            *.proto
             WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tests/proto/
             COMMENT "Generating test headers"
             )

+ 1 - 9
src/generator/classgeneratorbase.h

@@ -68,15 +68,6 @@ protected:
             return;
         }
 
-        Indent();
-        mPrinter.Print("Q_ENUMS(");
-        for (int i = 0; i < message->enum_type_count(); i++) {
-            const auto enumDescr = message->enum_type(i);
-            mPrinter.Print(enumDescr->name().c_str());
-        }
-        mPrinter.Print(")\n");
-        Outdent();
-
         printPublic();
 
         Indent();
@@ -91,6 +82,7 @@ protected:
             }
             Outdent();
             mPrinter.Print(SemicolonBlockEnclosureTemplate);
+            mPrinter.Print({{"type", enumDescr->name().c_str()}}, QEnumTemplate);
         }
         Outdent();
     }

+ 34 - 10
src/generator/generator.cpp

@@ -38,6 +38,7 @@
 #include <vector>
 #include <sstream>
 #include <string>
+#include <list>
 
 using namespace ::google::protobuf;
 using namespace ::google::protobuf::compiler;
@@ -139,16 +140,22 @@ class GlobalEnumsGenerator : public ClassGeneratorBase
     const FileDescriptor *mFile;
 
 public:
-    GlobalEnumsGenerator(const FileDescriptor *file, std::unique_ptr<io::ZeroCopyOutputStream> out) :
+    GlobalEnumsGenerator(std::unique_ptr<io::ZeroCopyOutputStream> out) :
         ClassGeneratorBase("GlobalEnums", std::move(out))
-    , mFile(file)
-    {}
-
-    void run() {
+    {
         printPreamble();
-        printNamespaces(mFile->package());
+    }
+
+    void startEnum(std::string package) {
+        printNamespaces(package);
         printEnumClass();
-        printQEnums<FileDescriptor>(mFile);
+    }
+
+    void run(const FileDescriptor *file) {
+        printQEnums<FileDescriptor>(file);
+    }
+
+    void encloseEnum() {
         encloseClass();
         enclose();
     }
@@ -187,9 +194,26 @@ bool QtGenerator::Generate(const FileDescriptor *file,
         classSourceGen.run();
     }
 
+    return true;
+}
+
+bool QtGenerator::GenerateAll(const std::vector<const FileDescriptor *> &files, const string &parameter, GeneratorContext *generatorContext, string *error) const
+{
     std::string globalEnumsFilename = "globalenums.h";
-    GlobalEnumsGenerator enumGen(file, std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(globalEnumsFilename))));
-    enumGen.run();
+    GlobalEnumsGenerator enumGen(std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(globalEnumsFilename))));
+    std::unordered_map<std::string/*package*/, std::list<const FileDescriptor */*file*/>> packageList;
+    for (auto file : files) {
+        packageList[file->package()].push_back(file);
+    }
 
-    return true;
+    for (auto package : packageList) {
+        enumGen.startEnum(package.first);
+        for(auto file : package.second) {
+            enumGen.run(file);
+        }
+        enumGen.encloseEnum();
+    }
+
+    return CodeGenerator::GenerateAll(files, parameter, generatorContext, error);
 }
+

+ 5 - 0
src/generator/generator.h

@@ -42,6 +42,11 @@ class QtGenerator : public ::google::protobuf::compiler::CodeGenerator
                           const std::string &parameter,
                           ::google::protobuf::compiler::GeneratorContext *generatorContext,
                           std::string *error) const override;
+
+    virtual bool GenerateAll(const std::vector<const ::google::protobuf::FileDescriptor *> &files,
+                             const std::string &parameter,
+                             ::google::protobuf::compiler::GeneratorContext *generatorContext,
+                             std::string *error) const override;
 };
 
 }  // namespace qtprotobuf

+ 2 - 0
src/generator/templates.h

@@ -108,6 +108,8 @@ static const char *EmptyBlockTemplate = "{}\n\n";
 static const char *DeclareMetaTypeTemplate = "#include <QMetaType>\n"
                                              "Q_DECLARE_METATYPE($namespaces$::$type$)\n";
 
+static const char *QEnumTemplate = "Q_ENUM($type$)\n";
+
 
 static const std::unordered_map<::google::protobuf::FieldDescriptor::Type, std::string> TypeReflection = {
     {::google::protobuf::FieldDescriptor::TYPE_DOUBLE, "double"},

+ 11 - 0
tests/proto/globalenums.proto

@@ -0,0 +1,11 @@
+syntax = "proto3";
+
+package qtprotobufnamespace.tests.globalenums;
+
+enum TestEnum {
+    TEST_ENUM_VALUE0 = 0;
+    TEST_ENUM_VALUE1 = 1;
+    TEST_ENUM_VALUE2 = 2;
+    TEST_ENUM_VALUE3 = 4;
+    TEST_ENUM_VALUE4 = 3;
+}

+ 11 - 0
tests/proto/globalenumssamenamespace.proto

@@ -0,0 +1,11 @@
+syntax = "proto3";
+
+package qtprotobufnamespace.tests;
+
+enum TestEnum2 {
+    TEST_ENUM2_VALUE0 = 0;
+    TEST_ENUM2_VALUE1 = 1;
+    TEST_ENUM2_VALUE2 = 2;
+    TEST_ENUM2_VALUE3 = 4;
+    TEST_ENUM2_VALUE4 = 3;
+}

+ 9 - 1
tests/simpletest.cpp

@@ -124,7 +124,15 @@ TEST_F(SimpleTest, SimpleDoubleMessageTest)
 TEST_F(SimpleTest, SimpleEnumsTest)
 {
     ASSERT_GT(GlobalEnums::staticMetaObject.enumeratorCount(), 0);
-    QMetaEnum simpleEnum = GlobalEnums::staticMetaObject.enumerator(0);
+    QMetaEnum simpleEnum;
+    for(int i = 0; i < GlobalEnums::staticMetaObject.enumeratorCount(); i++) {
+        QMetaEnum tmp = GlobalEnums::staticMetaObject.enumerator(i);
+        if (QString(tmp.name()) == QString("TestEnum")) {
+            simpleEnum = tmp;
+            break;
+        }
+    }
+    ASSERT_TRUE(simpleEnum.isValid());
     ASSERT_STREQ(simpleEnum.key(0), "TEST_ENUM_VALUE0");
     ASSERT_STREQ(simpleEnum.key(1), "TEST_ENUM_VALUE1");
     ASSERT_STREQ(simpleEnum.key(2), "TEST_ENUM_VALUE2");