Browse Source

Add local enum logic for messages

Tatyana Borisova 6 years ago
parent
commit
06e8853f22

+ 6 - 0
src/generator/classgeneratorbase.h

@@ -77,6 +77,7 @@ protected:
         for (int i = 0; i < message->enum_type_count(); i++) {
             const auto enumDescr = message->enum_type(i);
             mPrinter.Print({{"enum", enumDescr->name()}}, Templates::EnumDefinitionTemplate);
+
             Indent();
             for (int j = 0; j < enumDescr->value_count(); j++) {
                 const auto valueDescr = enumDescr->value(j);
@@ -87,6 +88,11 @@ protected:
             mPrinter.Print(Templates::SemicolonBlockEnclosureTemplate);
             mPrinter.Print({{"type", enumDescr->name().c_str()}}, Templates::QEnumTemplate);
         }
+
+        for (int i = 0; i < message->enum_type_count(); i++) {
+            const auto enumDescr = message->enum_type(i);
+            mPrinter.Print({{"enum", enumDescr->name()}}, Templates::EnumTypeUsingTemplate);
+        }
         Outdent();
     }
 

+ 28 - 7
src/generator/protobufclassgenerator.cpp

@@ -84,7 +84,12 @@ void ProtobufClassGenerator::printMoveSemantic()
         if (isComplexType(field) || field->is_repeated()) {
             printField(field, Templates::MoveComplexFieldTemplate);
         } else {
-            printField(field, Templates::MoveFieldTemplate);
+            if (field->type() != FieldDescriptor::TYPE_ENUM) {
+                printField(field, Templates::MoveFieldTemplate);
+            }
+            else {
+                printField(field, Templates::EnumMoveFieldTemplate);
+            }
         }
     }
     Outdent();
@@ -99,7 +104,12 @@ void ProtobufClassGenerator::printMoveSemantic()
         if (isComplexType(field) || field->is_repeated()) {
             printField(field, Templates::MoveComplexFieldTemplate);
         } else {
-            printField(field, Templates::MoveFieldTemplate);
+            if (field->type() != FieldDescriptor::TYPE_ENUM) {
+                printField(field, Templates::MoveFieldTemplate);
+            }
+            else {
+                printField(field, Templates::EnumMoveFieldTemplate);
+            }
         }
     }
     mPrinter.Print(Templates::AssignmentOperatorReturnTemplate);
@@ -158,6 +168,8 @@ void ProtobufClassGenerator::printIncludes(std::set<std::string> listModel)
                 includeTemplate = Templates::InternalIncludeTemplate;
             } else if (field->type() == FieldDescriptor::TYPE_STRING) {
                 includeTemplate = Templates::ExternalIncludeTemplate;
+            } else if (field->type() == FieldDescriptor::TYPE_ENUM) {
+                includeTemplate = Templates::GlobalEnumIncludeTemplate;
             } else {
                 continue;
             }
@@ -209,10 +221,10 @@ std::string ProtobufClassGenerator::getTypeName(const FieldDescriptor *field)
             return typeName.append("List");
         }
     } else if (field->type() == FieldDescriptor::TYPE_ENUM) {
+        typeName = field->enum_type()->name();
         if (field->is_repeated()) {
-            return VariantList;
+            return typeName.append("List");
         }
-        typeName = field->enum_type()->name();
     } else {
         auto it = Templates::TypeReflection.find(field->type());
         if (it != std::end(Templates::TypeReflection)) {
@@ -291,9 +303,7 @@ void ProtobufClassGenerator::printProperties()
                                                                                         Templates::PropertyTemplate;
         printField(field, propertyTemplate);
     }
-    for (int i = 0; i < mMessage->field_count(); i++) {
-        printField(mMessage->field(i), Templates::MemberTemplate);
-    }
+
     Outdent();
 
     printQEnums(mMessage);
@@ -339,6 +349,7 @@ void ProtobufClassGenerator::printRegisterTypes()
 void ProtobufClassGenerator::printListType()
 {
     mPrinter.Print({{"classname", mClassName}}, Templates::ComplexListTypeUsingTemplate);
+
 }
 
 void ProtobufClassGenerator::printFieldsOrderingDefinition()
@@ -348,6 +359,15 @@ void ProtobufClassGenerator::printFieldsOrderingDefinition()
     Outdent();
 }
 
+void ProtobufClassGenerator::printClassMembers()
+{
+    Indent();
+    for (int i = 0; i < mMessage->field_count(); i++) {
+        printField(mMessage->field(i), Templates::MemberTemplate);
+    }
+    Outdent();
+}
+
 std::set<std::string> ProtobufClassGenerator::extractModels() const
 {
     std::set<std::string> extractedModels;
@@ -372,6 +392,7 @@ void ProtobufClassGenerator::run()
     printProperties();
     printPublic();
     printFieldsOrderingDefinition();
+    printClassMembers();
     encloseClass();
     printListType();
     encloseNamespaces();

+ 1 - 0
src/generator/protobufclassgenerator.h

@@ -59,6 +59,7 @@ public:
     void printField(const ::google::protobuf::FieldDescriptor *field, const char *fieldTemplate);
     void printProperties();
     void printFieldsOrderingDefinition();
+    void printClassMembers();
     void printRegisterTypes();
     void printConstructor();
     void printListType();

+ 40 - 36
src/generator/templates.cpp

@@ -28,41 +28,44 @@
 using namespace qtprotobuf::generator;
 
 const char *Templates::DefaultProtobufIncludesTemplate = "#include <QMetaType>\n"
-                                              "#include <protobufobject.h>\n"
-                                              "#include <unordered_map>\n\n";
+                                                         "#include <protobufobject.h>\n"
+                                                         "#include <unordered_map>\n\n";
 
 const char *Templates::PreambleTemplate = "/* This file is autogenerated. DO NOT CHANGE. All changes will be lost */\n\n"
-                                      "#pragma once\n\n"
-                                      "#include <QObject>\n"
-                                      "#include <QMetaType>\n"
-                                      "#include <protobufobject.h>\n"
-                                      "#include <unordered_map>\n\n";
+                                          "#pragma once\n\n"
+                                          "#include <QObject>\n"
+                                          "#include <QMetaType>\n"
+                                          "#include <protobufobject.h>\n"
+                                          "#include <unordered_map>\n\n";
 
 const char *Templates::InternalIncludeTemplate =  "#include \"$type_lower$.h\"\n";
 const char *Templates::ExternalIncludeTemplate = "#include <$type$>\n";
 const char *Templates::ListModelsIncludeTemplate = "#include <QList>\n";
+const char *Templates::GlobalEnumIncludeTemplate = "#include <globalenums.h>\n";
 
 const char *Templates::UsingQtProtobufNamespaceTemplate = "\nusing namespace qtprotobuf;\n";
-const char *Templates::ComplexTypeRegistrationMethodTemplate = "\nstatic void registerTypes();\n";
+const char *Templates::ComplexTypeRegistrationMethodTemplate = "\n    static void registerTypes();\n";
 const char *Templates::ComplexTypeRegistrationTemplate = "void $classname$::registerTypes()\n{\n"
-                                                     "    static bool registationDone = false;\n"
-                                                     "    if (!registationDone) {\n\n"
-                                                     "        int metaTypeId = qRegisterMetaType<$classname$>(\"$classname$\");\n"
-                                                     "        int listMetaTypeId = qRegisterMetaType<$classname$List>(\"$classname$List\");\n"
-                                                     "        qRegisterMetaType<$namespaces$::$classname$>(\"$namespaces$::$classname$\");\n"
-                                                     "        qRegisterMetaType<$namespaces$::$classname$List>(\"$namespaces$::$classname$List\");\n"
-                                                     "        registerSerializers(metaTypeId, listMetaTypeId);\n"
-                                                     "    }\n}\n";
+                                                         "    static bool registationDone = false;\n"
+                                                         "    if (!registationDone) {\n\n"
+                                                         "        int metaTypeId = qRegisterMetaType<$classname$>(\"$classname$\");\n"
+                                                         "        int listMetaTypeId = qRegisterMetaType<$classname$List>(\"$classname$List\");\n"
+                                                         "        qRegisterMetaType<$namespaces$::$classname$>(\"$namespaces$::$classname$\");\n"
+                                                         "        qRegisterMetaType<$namespaces$::$classname$List>(\"$namespaces$::$classname$List\");\n"
+                                                         "        registerSerializers(metaTypeId, listMetaTypeId);\n"
+                                                         "    }\n}\n";
 const char *Templates::ComplexListTypeUsingTemplate = "using $classname$List = QList<$classname$>;\n";
 
+const char *Templates::EnumTypeUsingTemplate = "using $enum$List = QList<$enum$>;\n";
+
 const char *Templates::NamespaceTemplate = "\nnamespace $namespace$ {\n";
 
 const char *Templates::NonProtoClassDefinitionTemplate = "\nclass $classname$ : public QObject\n"
-                                                     "{\n"
-                                                     "    Q_OBJECT\n";
+                                                         "{\n"
+                                                         "    Q_OBJECT\n";
 const char *Templates::ClassDefinitionTemplate = "\nclass $classname$ final : public qtprotobuf::ProtobufObject<$classname$>\n"
-                                             "{\n"
-                                             "    Q_OBJECT\n";
+                                                 "{\n"
+                                                 "    Q_OBJECT\n";
 
 const char *Templates::PropertyTemplate = "Q_PROPERTY($type$ $property_name$ READ $property_name$ WRITE set$property_name_cap$ NOTIFY $property_name$Changed)\n";
 const char *Templates::MessagePropertyTemplate = "Q_PROPERTY($type$ $property_name$ READ $property_name$ WRITE set$property_name_cap$ NOTIFY $property_name$Changed)\n";
@@ -76,33 +79,34 @@ const char *Templates::MoveConstructorTemplate = "$classname$($classname$ &&othe
 const char *Templates::CopyFieldTemplate = "m_$property_name$ = other.m_$property_name$;\n";
 const char *Templates::MoveComplexFieldTemplate = "m_$property_name$ = std::move(other.m_$property_name$);\n";
 const char *Templates::MoveFieldTemplate = "m_$property_name$ = std::exchange(other.m_$property_name$, 0);\n";
+const char *Templates::EnumMoveFieldTemplate = "m_$property_name$ = other.m_$property_name$;\n";
 const char *Templates::AssignmentOperatorTemplate = "$classname$ &operator =(const $classname$ &other) {\n";
 const char *Templates::AssignmentOperatorReturnTemplate = "return *this;\n";
 const char *Templates::MoveAssignmentOperatorTemplate = "$classname$ &operator =($classname$ &&other) {\n";
 const char *Templates::EqualOperatorTemplate = "bool operator ==(const $type$ &other) const {\n"
-                                           "    return ";
+                                               "    return ";
 const char *Templates::EqualOperatorPropertyTemplate = "m_$property_name$ == other.m_$property_name$";
 const char *Templates::NotEqualOperatorTemplate = "bool operator !=(const $type$ &other) const {\n"
-                                              "    return !this->operator ==(other);\n"
-                                              "}\n\n";
+                                                  "    return !this->operator ==(other);\n"
+                                                  "}\n\n";
 
 const char *Templates::GetterTemplate = "$type$ $property_name$() const {\n"
-                                    "    return m_$property_name$;\n"
-                                    "}\n\n";
+                                        "    return m_$property_name$;\n"
+                                        "}\n\n";
 
 const char *Templates::SetterTemplateSimpleType = "void set$property_name_cap$($type$ $property_name$) {\n"
-                                              "    if (m_$property_name$ != $property_name$) {\n"
-                                              "        m_$property_name$ = $property_name$;\n"
-                                              "        $property_name$Changed();\n"
-                                              "    }\n"
-                                              "}\n\n";
+                                                  "    if (m_$property_name$ != $property_name$) {\n"
+                                                  "        m_$property_name$ = $property_name$;\n"
+                                                  "        $property_name$Changed();\n"
+                                                  "    }\n"
+                                                  "}\n\n";
 
 const char *Templates::SetterTemplateComplexType = "void set$property_name_cap$(const $type$ &$property_name$) {\n"
-                                               "    if (m_$property_name$ != $property_name$) {\n"
-                                               "        m_$property_name$ = $property_name$;\n"
-                                               "        $property_name$Changed();\n"
-                                               "    }\n"
-                                               "}\n\n";
+                                                   "    if (m_$property_name$ != $property_name$) {\n"
+                                                   "        m_$property_name$ = $property_name$;\n"
+                                                   "        $property_name$Changed();\n"
+                                                   "    }\n"
+                                                   "}\n\n";
 
 const char *Templates::SignalsBlockTemplate = "\nsignals:\n";
 const char *Templates::SignalTemplate = "void $property_name$Changed();\n";
@@ -139,7 +143,7 @@ const std::unordered_map<::google::protobuf::FieldDescriptor::Type, std::string>
     //    {FieldDescriptor::TYPE_MESSAGE, ""},//Custom typename
     {::google::protobuf::FieldDescriptor::TYPE_BYTES, "QByteArray"},
     {::google::protobuf::FieldDescriptor::TYPE_UINT32, "int"},//Limited usage see https://doc.qt.io/qt-5/qtqml-typesystem-basictypes.html
-    //    {FieldDescriptor::TYPE_ENUM, ""},//Custom typename
+    {::google::protobuf::FieldDescriptor::TYPE_ENUM, ""},//Custom typename
     {::google::protobuf::FieldDescriptor::TYPE_SFIXED32, "int"},
     //        {FieldDescriptor::TYPE_SFIXED64, "int"},//Not supported see https://doc.qt.io/qt-5/qtqml-typesystem-basictypes.html
     {::google::protobuf::FieldDescriptor::TYPE_SINT32, "int"},

+ 3 - 0
src/generator/templates.h

@@ -39,10 +39,12 @@ public:
     static const char *InternalIncludeTemplate;
     static const char *ExternalIncludeTemplate;
     static const char *ListModelsIncludeTemplate;
+    static const char *GlobalEnumIncludeTemplate;
     static const char *UsingQtProtobufNamespaceTemplate;
     static const char *ComplexTypeRegistrationMethodTemplate;
     static const char *ComplexTypeRegistrationTemplate;
     static const char *ComplexListTypeUsingTemplate;
+    static const char *EnumTypeUsingTemplate;
     static const char *NamespaceTemplate;
     static const char *NonProtoClassDefinitionTemplate;
     static const char *ClassDefinitionTemplate;
@@ -58,6 +60,7 @@ public:
     static const char *CopyFieldTemplate;
     static const char *MoveComplexFieldTemplate;
     static const char *MoveFieldTemplate;
+    static const char *EnumMoveFieldTemplate;
     static const char *AssignmentOperatorTemplate;
     static const char *AssignmentOperatorReturnTemplate;
     static const char *MoveAssignmentOperatorTemplate;

+ 12 - 0
tests/proto/simpletest.proto

@@ -2,6 +2,18 @@ syntax = "proto3";
 
 package qtprotobufnamespace.tests;
 
+message SimpleEnumMessage {
+  enum LocalEnum {
+    LOCAL_ENUM_VALUE0 = 0;
+    LOCAL_ENUM_VALUE1 = 1;
+    LOCAL_ENUM_VALUE2 = 2;
+    LOCAL_ENUM_VALUE3 = 3;
+  }
+
+  LocalEnum localEnum = 1;
+  repeated LocalEnum localEnumList = 2;
+}
+
 message SimpleIntMessage {
     int32 testFieldInt = 1;
 }

+ 24 - 0
tests/simpletest.cpp

@@ -31,6 +31,7 @@
 #include "simplestringmessage.h"
 #include "simplefloatmessage.h"
 #include "simpledoublemessage.h"
+#include "simpleenummessage.h"
 #include "complexmessage.h"
 #include "repeatedintmessage.h"
 #include "simplebytesmessage.h"
@@ -121,6 +122,29 @@ TEST_F(SimpleTest, SimpleDoubleMessageTest)
     ASSERT_FLOAT_EQ(test.testFieldDouble(), 0.55);
 }
 
+TEST_F(SimpleTest, SimpleLocalEnumsTest)
+{
+    ASSERT_GT(SimpleEnumMessage::staticMetaObject.enumeratorCount(), 0);
+    QMetaEnum simpleEnum;
+    for (int i = 0; i < SimpleEnumMessage::staticMetaObject.enumeratorCount(); i++) {
+        QMetaEnum tmp = SimpleEnumMessage::staticMetaObject.enumerator(i);
+        if (QString(tmp.name()) == QString("LocalEnum")) {
+            simpleEnum = tmp;
+            break;
+        }
+    }
+    ASSERT_TRUE(simpleEnum.isValid());
+    ASSERT_STREQ(simpleEnum.key(0), "LOCAL_ENUM_VALUE0");
+    ASSERT_STREQ(simpleEnum.key(1), "LOCAL_ENUM_VALUE1");
+    ASSERT_STREQ(simpleEnum.key(2), "LOCAL_ENUM_VALUE2");
+    ASSERT_STREQ(simpleEnum.key(3), "LOCAL_ENUM_VALUE3");
+
+    ASSERT_EQ(simpleEnum.value(0), 0);
+    ASSERT_EQ(simpleEnum.value(1), 1);
+    ASSERT_EQ(simpleEnum.value(2), 2);
+    ASSERT_EQ(simpleEnum.value(3), 3);
+}
+
 TEST_F(SimpleTest, SimpleEnumsTest)
 {
     ASSERT_GT(GlobalEnums::staticMetaObject.enumeratorCount(), 0);