Browse Source

Complete migration to pointers

- Migrate to unique_ptr for complex message fields
- Resolve cycling and position related issues in
  generated code
- Implements tests
- Minor code cleanup
Alexey Edelev 5 years ago
parent
commit
9f69cac302

+ 58 - 1
src/generator/classgeneratorbase.cpp

@@ -168,7 +168,7 @@ std::string ClassGeneratorBase::getTypeName(const FieldDescriptor *field, const
             if (field->is_repeated()) {
                 typeName = typeName.append(mClassName + "::" + enumType->name());
             } else {
-                typeName = typeName.append(enumType->name());
+                typeName = typeName.append(mClassName + "::" + enumType->name());
             }
         } else if (visibility == GLOBAL_ENUM) {
             namespaceTypeName = getNamespacesList(enumType, typeNamespace, "");
@@ -285,3 +285,60 @@ bool ClassGeneratorBase::hasGlobalEnum(const std::list<const FileDescriptor *> &
     }
     return true;
 }
+
+void ClassGeneratorBase::printField(const google::protobuf::Descriptor *message, const FieldDescriptor *field, const char *fieldTemplate)
+{
+    assert(field != nullptr);
+    std::map<std::string, std::string> propertyMap;
+    if (producePropertyMap(message, field, propertyMap)) {
+        mPrinter->Print(propertyMap, fieldTemplate);
+    }
+}
+
+bool ClassGeneratorBase::producePropertyMap(const google::protobuf::Descriptor *message, const FieldDescriptor *field, PropertyMap &propertyMap)
+{
+    assert(field != nullptr);
+    std::string typeName = getTypeName(field, message);
+
+    if (typeName.size() <= 0) {
+        std::cerr << "Type "
+                  << field->type_name()
+                  << " is not supported by Qt Generator"
+                     " please look at https://doc.qt.io/qt-5/qtqml-typesystem-basictypes.html"
+                     " for details" << std::endl;
+        return false;
+    }
+
+    std::string typeNameLower(typeName);
+    utils::tolower(typeNameLower);
+
+    std::string capProperty = field->name();
+    capProperty[0] = static_cast<char>(::toupper(capProperty[0]));
+
+    std::string typeNameNoList = typeName;
+    if (field->is_repeated() && !field->is_map()) {
+        if(field->type() == FieldDescriptor::TYPE_MESSAGE
+                || field->type() == FieldDescriptor::TYPE_ENUM) {
+            typeNameNoList.resize(typeNameNoList.size() - strlen(Templates::ListSuffix));
+        } else {
+            typeNameNoList.resize(typeNameNoList.size() - strlen("List"));
+        }
+    }
+    propertyMap = {{"type", typeName},
+                   {"classname", message->name()},
+                   {"type_lower", typeNameLower},
+                   {"property_name", field->name()},
+                   {"property_name_cap", capProperty},
+                   {"type_nolist", typeNameNoList}
+                  };
+    return true;
+}
+
+bool ClassGeneratorBase::isComplexType(const FieldDescriptor *field)
+{
+    assert(field != nullptr);
+    return field->type() == FieldDescriptor::TYPE_MESSAGE
+            || field->type() == FieldDescriptor::TYPE_STRING
+            || field->type() == FieldDescriptor::TYPE_BYTES;
+}
+

+ 3 - 0
src/generator/classgeneratorbase.h

@@ -77,6 +77,9 @@ public:
     void encloseNamespaces();
     void encloseNamespaces(int count);
     bool hasGlobalEnum(const std::list<const ::google::protobuf::FileDescriptor *> &list);
+    void printField(const google::protobuf::Descriptor *message, const ::google::protobuf::FieldDescriptor *field, const char *fieldTemplate);
+    bool producePropertyMap(const google::protobuf::Descriptor *message, const ::google::protobuf::FieldDescriptor *field, PropertyMap &propertyMap);
+    bool isComplexType(const google::protobuf::FieldDescriptor *field);
 
     template<typename T>
     void printQEnums(const T *message) {

+ 46 - 187
src/generator/protobufclassgenerator.cpp

@@ -53,130 +53,29 @@ void ProtobufClassGenerator::printCopyFunctionality()
 {
     assert(mMessage != nullptr);
     mPrinter->Print({{"classname", mClassName}},
-                   Templates::CopyConstructorTemplate);
+                   Templates::CopyConstructorDeclarationTemplate);
 
-    Indent();
-    for (int i = 0; i < mMessage->field_count(); i++) {
-        auto field = mMessage->field(i);
-        if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
-            printField(field, Templates::CopyComplexFieldTemplate);
-        } else {
-            printField(field, Templates::CopyFieldTemplate);
-        }
-    }
-    Outdent();
-
-    mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
     mPrinter->Print({{"classname", mClassName}},
-                   Templates::AssignmentOperatorTemplate);
-
-    Indent();
-    for (int i = 0; i < mMessage->field_count(); i++) {
-        auto field = mMessage->field(i);
-        if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
-            printField(field, Templates::CopyComplexFieldTemplate);
-        } else {
-            printField(field, Templates::CopyFieldTemplate);
-        }
-    }
-    mPrinter->Print(Templates::AssignmentOperatorReturnTemplate);
-    Outdent();
-
-    mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
+                   Templates::AssignmentOperatorDeclarationTemplate);
 }
 
 void ProtobufClassGenerator::printMoveSemantic()
 {
     assert(mMessage != nullptr);
     mPrinter->Print({{"classname", mClassName}},
-                   Templates::MoveConstructorTemplate);
-
-    Indent();
-    for (int i = 0; i < mMessage->field_count(); i++) {
-        const FieldDescriptor *field = mMessage->field(i);
-        if (isComplexType(field) || field->is_repeated()) {
-            if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
-                printField(field, Templates::MoveMessageFieldTemplate);
-            } else {
-                printField(field, Templates::MoveComplexFieldTemplate);
-            }
-        } else {
-            if (field->type() != FieldDescriptor::TYPE_ENUM) {
-                printField(field, Templates::MoveFieldTemplate);
-            }
-            else {
-                printField(field, Templates::EnumMoveFieldTemplate);
-            }
-        }
-    }
-    Outdent();
+                   Templates::MoveConstructorDeclarationTemplate);
 
-    mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
     mPrinter->Print({{"classname", mClassName}},
-                   Templates::MoveAssignmentOperatorTemplate);
-
-    Indent();
-    for (int i = 0; i < mMessage->field_count(); i++) {
-        const FieldDescriptor *field = mMessage->field(i);
-        if (isComplexType(field) || field->is_repeated()) {
-            if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
-                printField(field, Templates::MoveMessageFieldTemplate);
-            } else {
-                printField(field, Templates::MoveComplexFieldTemplate);
-            }
-        } else {
-            if (field->type() != FieldDescriptor::TYPE_ENUM) {
-                printField(field, Templates::MoveFieldTemplate);
-            }
-            else {
-                printField(field, Templates::EnumMoveFieldTemplate);
-            }
-        }
-    }
-    mPrinter->Print(Templates::AssignmentOperatorReturnTemplate);
-    Outdent();
-
-    mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
+                   Templates::MoveAssignmentOperatorDeclarationTemplate);
 }
 
 void ProtobufClassGenerator::printComparisonOperators()
 {
     assert(mMessage != nullptr);
-    bool isFirst = true;
     PropertyMap properties;
-    mPrinter->Print({{"type", mClassName}}, Templates::EqualOperatorTemplate);
-    if (mMessage->field_count() <= 0) {
-        mPrinter->Print("true");
-    }
-    for (int i = 0; i < mMessage->field_count(); i++) {
-        const FieldDescriptor *field = mMessage->field(i);
-        if (producePropertyMap(field, properties)) {
-            if (!isFirst) {
-                mPrinter->Print("\n&& ");
-            } else {
-                Indent();
-                Indent();
-                isFirst = false;
-            }
-            if (field->type() == FieldDescriptor::TYPE_MESSAGE
-                    && !field->is_map() && !field->is_repeated()) {
-                mPrinter->Print(properties, Templates::EqualOperatorMessagePropertyTemplate);
-            } else {
-                mPrinter->Print(properties, Templates::EqualOperatorPropertyTemplate);
-            }
-        }
-    }
+    mPrinter->Print({{"classname", mClassName}}, Templates::EqualOperatorDeclarationTemplate);
 
-    //Only if at least one field "copied"
-    if (!isFirst) {
-        Outdent();
-        Outdent();
-    }
-
-    mPrinter->Print(";\n");
-    mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
-
-    mPrinter->Print({{"type", mClassName}}, Templates::NotEqualOperatorTemplate);
+    mPrinter->Print({{"classname", mClassName}}, Templates::NotEqualOperatorDeclarationTemplate);
 }
 
 void ProtobufClassGenerator::printIncludes()
@@ -250,53 +149,6 @@ void ProtobufClassGenerator::printInclude(const FieldDescriptor *field, std::set
     }
 }
 
-void ProtobufClassGenerator::printField(const FieldDescriptor *field, const char *fieldTemplate)
-{
-    assert(field != nullptr);
-    std::map<std::string, std::string> propertyMap;
-    if (producePropertyMap(field, propertyMap)) {
-        mPrinter->Print(propertyMap, fieldTemplate);
-    }
-}
-
-bool ProtobufClassGenerator::producePropertyMap(const FieldDescriptor *field, PropertyMap &propertyMap)
-{
-    assert(field != nullptr);
-    std::string typeName = getTypeName(field, mMessage);
-
-    if (typeName.size() <= 0) {
-        std::cerr << "Type "
-                  << field->type_name()
-                  << " is not supported by Qt Generator"
-                     " please look at https://doc.qt.io/qt-5/qtqml-typesystem-basictypes.html"
-                     " for details" << std::endl;
-        return false;
-    }
-
-    std::string typeNameLower(typeName);
-    utils::tolower(typeNameLower);
-
-    std::string capProperty = field->name();
-    capProperty[0] = static_cast<char>(::toupper(capProperty[0]));
-
-    std::string typeNameNoList = typeName;
-    if (field->is_repeated() && !field->is_map()) {
-        if(field->type() == FieldDescriptor::TYPE_MESSAGE
-                || field->type() == FieldDescriptor::TYPE_ENUM) {
-            typeNameNoList.resize(typeNameNoList.size() - strlen(Templates::ListSuffix));
-        } else {
-            typeNameNoList.resize(typeNameNoList.size() - strlen("List"));
-        }
-    }
-    propertyMap = {{"type", typeName},
-                   {"type_lower", typeNameLower},
-                   {"property_name", field->name()},
-                   {"property_name_cap", capProperty},
-                   {"type_nolist", typeNameNoList}
-                  };
-    return true;
-}
-
 bool ProtobufClassGenerator::isListType(const FieldDescriptor *field)
 {
     assert(field != nullptr);
@@ -304,29 +156,21 @@ bool ProtobufClassGenerator::isListType(const FieldDescriptor *field)
             && field->type() == FieldDescriptor::TYPE_MESSAGE;
 }
 
-bool ProtobufClassGenerator::isComplexType(const FieldDescriptor *field)
-{
-    assert(field != nullptr);
-    return field->type() == FieldDescriptor::TYPE_MESSAGE
-            || field->type() == FieldDescriptor::TYPE_STRING
-            || field->type() == FieldDescriptor::TYPE_BYTES;
-}
-
 void ProtobufClassGenerator::printConstructor()
 {
-    std::string parameterList;
+    std::vector<std::string> parameterList;
     for (int i = 0; i < mMessage->field_count(); i++) {
         const FieldDescriptor *field = mMessage->field(i);
         std::string fieldTypeName = getTypeName(field, mMessage);
         std::string fieldName = field->name();
         fieldName[0] = static_cast<char>(::tolower(fieldName[0]));
         if (field->is_repeated() || field->is_map()) {
-            parameterList += "const " + fieldTypeName + " &" + fieldName + " = {}";
+            parameterList.push_back("const " + fieldTypeName + " &" + fieldName);
         } else {
             switch (field->type()) {
             case FieldDescriptor::TYPE_DOUBLE:
             case FieldDescriptor::TYPE_FLOAT:
-                parameterList += fieldTypeName + " " + fieldName + " = " + "0.0";
+                parameterList.push_back(fieldTypeName + " " + fieldName);
                 break;
             case FieldDescriptor::TYPE_FIXED32:
             case FieldDescriptor::TYPE_FIXED64:
@@ -336,26 +180,32 @@ void ProtobufClassGenerator::printConstructor()
             case FieldDescriptor::TYPE_SINT64:
             case FieldDescriptor::TYPE_UINT32:
             case FieldDescriptor::TYPE_UINT64:
-                parameterList += fieldTypeName + " " + fieldName + " = " + "0";
+                parameterList.push_back(fieldTypeName + " " + fieldName);
                 break;
             case FieldDescriptor::TYPE_BOOL:
-                parameterList += fieldTypeName + " " + fieldName + " = " + "false";
+                parameterList.push_back(fieldTypeName + " " + fieldName);
                 break;
             case FieldDescriptor::TYPE_BYTES:
             case FieldDescriptor::TYPE_STRING:
             case FieldDescriptor::TYPE_MESSAGE:
-                parameterList += "const " + fieldTypeName + " &" + fieldName + " = {}";
+                parameterList.push_back("const " + fieldTypeName + " &" + fieldName);
                 break;
             default:
-                parameterList += fieldTypeName + " " + fieldName + " = " + "{}";
+                parameterList.push_back(fieldTypeName + " " + fieldName);
                 break;
             }
         }
-        parameterList += ", ";
     }
-    mPrinter->Print({{"classname", mClassName},
-                    {"parameter_list", parameterList}}, Templates::ProtoConstructorTemplate);
 
+    for (size_t i = 0; i <= parameterList.size(); i++) {
+        std::string parameters = "";
+        for (size_t j = 0; j < i; j++) {
+            parameters += parameterList[j] + ", ";
+        }
+        mPrinter->Print({{"classname", mClassName},
+                        {"parameter_list", parameters}}, Templates::ProtoConstructorTemplate);
+    }
+    mPrinter->Print("\n");
 }
 
 void ProtobufClassGenerator::printMaps()
@@ -418,7 +268,7 @@ void ProtobufClassGenerator::printProperties()
         if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
             propertyTemplate = Templates::MessagePropertyTemplate;
         }
-        printField(field, propertyTemplate);
+        printField(mMessage, field, propertyTemplate);
     }
 
     //Generate extra QmlListProperty that is mapped to list
@@ -426,7 +276,7 @@ void ProtobufClassGenerator::printProperties()
         const FieldDescriptor *field = mMessage->field(i);
         if (field->type() == FieldDescriptor::TYPE_MESSAGE && field->is_repeated() && !field->is_map()
                 && GeneratorOptions::instance().hasQml()) {
-            printField(field, Templates::QmlListPropertyTemplate);
+            printField(mMessage, field, Templates::QmlListPropertyTemplate);
         }
     }
 
@@ -448,39 +298,41 @@ void ProtobufClassGenerator::printProperties()
     for (int i = 0; i < mMessage->field_count(); i++) {
         const FieldDescriptor *field = mMessage->field(i);
         if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
-                printField(field, Templates::GetterPrivateMessageTemplate);
-                printField(field, Templates::GetterMessageTemplate);
+            printField(mMessage, field, Templates::GetterPrivateMessageDeclarationTemplate);
+            printField(mMessage, field, Templates::GetterMessageDeclarationTemplate);
         } else {
-            printField(field, Templates::GetterTemplate);
+            printField(mMessage, field, Templates::GetterDeclarationTemplate);
         }
         if (field->is_repeated()) {
-            printField(field, Templates::GetterContainerExtraTemplate);
+            printField(mMessage, field, Templates::GetterContainerExtraDeclarationTemplate);
             if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map()
                     && GeneratorOptions::instance().hasQml()) {
-                printField(field, Templates::QmlListGetterTemplate);
+                printField(mMessage, field, Templates::GetterQmlListDeclarationTemplate);
             }
         }
     }
+
     for (int i = 0; i < mMessage->field_count(); i++) {
         auto field = mMessage->field(i);
         switch (field->type()) {
         case FieldDescriptor::TYPE_MESSAGE:
             if (!field->is_map() && !field->is_repeated()) {
-                printField(field, Templates::SetterPrivateTemplateMessageType);
-                printField(field, Templates::SetterTemplateMessageType);
+                printField(mMessage, field, Templates::SetterPrivateTemplateDeclarationMessageType);
+                printField(mMessage, field, Templates::SetterTemplateDeclarationMessageType);
             } else {
-                printField(field, Templates::SetterTemplateComplexType);
+                printField(mMessage, field, Templates::SetterTemplateDeclarationComplexType);
             }
             break;
         case FieldDescriptor::FieldDescriptor::TYPE_STRING:
         case FieldDescriptor::FieldDescriptor::TYPE_BYTES:
-            printField(field, Templates::SetterTemplateComplexType);
+            printField(mMessage, field, Templates::SetterTemplateDeclarationComplexType);
             break;
         default:
-            printField(field, Templates::SetterTemplateSimpleType);
+            printField(mMessage, field, Templates::SetterTemplateSimpleType);
             break;
         }
     }
+
     Outdent();
 
     Indent();
@@ -491,7 +343,7 @@ void ProtobufClassGenerator::printProperties()
 
     Indent();
     for (int i = 0; i < mMessage->field_count(); i++) {
-        printField(mMessage->field(i), Templates::SignalTemplate);
+        printField(mMessage, mMessage->field(i), Templates::SignalTemplate);
     }
     Outdent();
 }
@@ -508,9 +360,9 @@ void ProtobufClassGenerator::printClassMembers()
     for (int i = 0; i < mMessage->field_count(); i++) {
         auto field = mMessage->field(i);
         if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
-            printField(field, Templates::ComplexMemberTemplate);
+            printField(mMessage, field, Templates::ComplexMemberTemplate);
         } else {
-            printField(field, Templates::MemberTemplate);
+            printField(mMessage, field, Templates::MemberTemplate);
         }
     }
     Outdent();
@@ -540,6 +392,8 @@ void ProtobufClassGenerator::run()
     printProperties();
     printPrivate();
     printClassMembers();
+    printPublic();
+    printDestructor();
     encloseClass();
     printListType();
     encloseNamespaces();
@@ -547,3 +401,8 @@ void ProtobufClassGenerator::run()
     printMapsMetaTypesDeclaration();
     printLocalEmumsMetaTypesDeclaration();
 }
+
+void ProtobufClassGenerator::printDestructor()
+{
+    mPrinter->Print({{"classname", mClassName}}, "virtual ~$classname$();");
+}

+ 1 - 3
src/generator/protobufclassgenerator.h

@@ -57,10 +57,10 @@ public:
     void printCopyFunctionality();
     void printMoveSemantic();
     void printComparisonOperators();
-    void printField(const ::google::protobuf::FieldDescriptor *field, const char *fieldTemplate);
     void printProperties();
     void printClassMembers();
     void printConstructor();
+    void printDestructor();
     void printListType();
     void printInclude(const google::protobuf::FieldDescriptor *field, std::set<std::string> &existingIncludes);
     void printMaps();
@@ -70,8 +70,6 @@ public:
     std::set<std::string> extractModels() const;
 
 private:
-    bool producePropertyMap(const ::google::protobuf::FieldDescriptor *field, PropertyMap &propertyMap);
-    static bool isComplexType(const ::google::protobuf::FieldDescriptor *field);
     static bool isListType(const ::google::protobuf::FieldDescriptor *field);
 };
 

+ 252 - 14
src/generator/protobufsourcegenerator.cpp

@@ -71,6 +71,12 @@ void ProtobufSourceGenerator::printRegisterBody()
             mPrinter->Print({{"type", mClassName + "::" + field->enum_type()->name() + Templates::ListSuffix},
                             {"namespaces", mNamespacesColonDelimited}},
                            Templates::RegisterMetaTypeTemplate);
+            mPrinter->Print({{"type", mClassName + "::" + field->enum_type()->name()},
+                            {"namespaces", mNamespacesColonDelimited}},
+                           Templates::RegisterMetaTypeTemplateNoNamespace);
+            mPrinter->Print({{"type", mClassName + "::" + field->enum_type()->name()},
+                            {"namespaces", mNamespacesColonDelimited}},
+                           Templates::RegisterMetaTypeTemplate);
             mPrinter->Print({{"type", mClassName + "::" + field->enum_type()->name()}},
                            Templates::RegisterEnumSerializersTemplate);
         } else if (field->is_map()) {
@@ -113,19 +119,19 @@ void ProtobufSourceGenerator::printFieldsOrdering() {
 
 void ProtobufSourceGenerator::printConstructor()
 {
-    std::string parameterList;
+    std::vector<std::string> parameterList;
     for (int i = 0; i < mMessage->field_count(); i++) {
         const FieldDescriptor *field = mMessage->field(i);
         std::string fieldTypeName = getTypeName(field, mMessage);
         std::string fieldName = field->name();
         fieldName[0] = static_cast<char>(::tolower(fieldName[0]));
         if (field->is_repeated() || field->is_map()) {
-            parameterList += "const " + fieldTypeName + " &" + fieldName;
+            parameterList.push_back("const " + fieldTypeName + " &" + fieldName);
         } else {
             switch (field->type()) {
             case FieldDescriptor::TYPE_DOUBLE:
             case FieldDescriptor::TYPE_FLOAT:
-                parameterList += fieldTypeName + " " + fieldName;
+                parameterList.push_back(fieldTypeName + " " + fieldName);
                 break;
             case FieldDescriptor::TYPE_FIXED32:
             case FieldDescriptor::TYPE_FIXED64:
@@ -135,38 +141,270 @@ void ProtobufSourceGenerator::printConstructor()
             case FieldDescriptor::TYPE_SINT64:
             case FieldDescriptor::TYPE_UINT32:
             case FieldDescriptor::TYPE_UINT64:
-                parameterList += fieldTypeName + " " + fieldName;
+                parameterList.push_back(fieldTypeName + " " + fieldName);
                 break;
             case FieldDescriptor::TYPE_BOOL:
-                parameterList += fieldTypeName + " " + fieldName;
+                parameterList.push_back(fieldTypeName + " " + fieldName);
                 break;
             case FieldDescriptor::TYPE_BYTES:
             case FieldDescriptor::TYPE_STRING:
             case FieldDescriptor::TYPE_MESSAGE:
-                parameterList += "const " + fieldTypeName + " &" + fieldName;
+                parameterList.push_back("const " + fieldTypeName + " &" + fieldName);
                 break;
             default:
-                parameterList += fieldTypeName + " " + fieldName;
+                parameterList.push_back(fieldTypeName + " " + fieldName);
                 break;
             }
         }
-        parameterList += ", ";
     }
-    mPrinter->Print({{"classname", mClassName},
-                    {"parameter_list", parameterList}}, Templates::ProtoConstructorDefinitionTemplate);
 
+    for (size_t i = 0; i <= parameterList.size(); i++) {
+        std::string parameters = "";
+        for (size_t j = 0; j < i; j++) {
+            parameters += parameterList[j] + ", ";
+        }
+        mPrinter->Print({{"classname", mClassName},
+                        {"parameter_list", parameters}}, Templates::ProtoConstructorDefinitionTemplate);
+        for (size_t j = 0; j < parameterList.size(); j++) {
+            const FieldDescriptor *field = mMessage->field(j);
+            std::string fieldName = field->name();
+            auto fieldTypeName = getTypeName(field, mMessage);
+            fieldName[0] =  static_cast<char>(::tolower(fieldName[0]));
+            if (field->type() == FieldDescriptor::TYPE_MESSAGE
+                    && !field->is_map() && !field->is_repeated()) {
+                if (j < i) {
+                    mPrinter->Print({{"property_name", fieldName}, {"type", fieldTypeName}}, Templates::MessagePropertyInitializerTemplate);
+                } else {
+                    mPrinter->Print({{"property_name", fieldName}, {"type", fieldTypeName}}, Templates::MessagePropertyEmptyInitializerTemplate);
+                }
+            } else {
+                if (j < i) {
+                    mPrinter->Print({{"property_name", fieldName}}, Templates::PropertyInitializerTemplate);
+                } else {
+                    std::string initializer = "";
+                    if (!field->is_repeated() && !field->is_map()) {
+                        switch (field->type()) {
+                        case FieldDescriptor::TYPE_DOUBLE:
+                        case FieldDescriptor::TYPE_FLOAT:
+                            initializer = "0.0";
+                            break;
+                        case FieldDescriptor::TYPE_FIXED32:
+                        case FieldDescriptor::TYPE_FIXED64:
+                        case FieldDescriptor::TYPE_INT32:
+                        case FieldDescriptor::TYPE_INT64:
+                        case FieldDescriptor::TYPE_SINT32:
+                        case FieldDescriptor::TYPE_SINT64:
+                        case FieldDescriptor::TYPE_UINT32:
+                        case FieldDescriptor::TYPE_UINT64:
+                            initializer = "0";
+                            break;
+                        case FieldDescriptor::TYPE_BOOL:
+                            initializer = "false";
+                            break;
+                        default:
+                            break;
+                        }
+                    }
+                    if (initializer != "") {
+                        mPrinter->Print({{"property_name", fieldName}, {"initializer", initializer}}, Templates::PropertyEmptyInitializerTemplate);
+                    }
+                }
+            }
+        }
+        mPrinter->Print(Templates::ConstructorContentTemplate);
+        mPrinter->Print("\n");
+    }
+}
+
+void ProtobufSourceGenerator::printCopyFunctionality()
+{
+    mPrinter->Print({{"classname", mClassName}},
+                   Templates::CopyConstructorDefinitionTemplate);
+    for (int j = 0; j < mMessage->field_count(); j++) {
+        const FieldDescriptor *field = mMessage->field(j);
+        std::string fieldName = field->name();
+        auto fieldTypeName = getTypeName(field, mMessage);
+        fieldName[0] =  static_cast<char>(::tolower(fieldName[0]));
+        if (field->type() == FieldDescriptor::TYPE_MESSAGE
+                && !field->is_map() && !field->is_repeated()) {
+            mPrinter->Print({{"property_name", fieldName}, {"type", fieldTypeName}}, Templates::MessagePropertyEmptyInitializerTemplate);
+        }
+    }
+    mPrinter->Print("\n{\n");
+
+    Indent();
     for (int i = 0; i < mMessage->field_count(); i++) {
-        const FieldDescriptor *field = mMessage->field(i);
+        auto field = mMessage->field(i);
+        if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
+            printField(mMessage, field, Templates::CopyComplexFieldTemplate);
+        } else {
+            printField(mMessage, field, Templates::CopyFieldTemplate);
+        }
+    }
+    Outdent();
+    mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
+
+    mPrinter->Print({{"classname", mClassName}},
+                   Templates::AssignmentOperatorDefinitionTemplate);
+    Indent();
+    for (int i = 0; i < mMessage->field_count(); i++) {
+        auto field = mMessage->field(i);
+        if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
+            printField(mMessage, field, Templates::CopyComplexFieldTemplate);
+        } else {
+            printField(mMessage, field, Templates::CopyFieldTemplate);
+        }
+    }
+    mPrinter->Print(Templates::AssignmentOperatorReturnTemplate);
+    Outdent();
+    mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
+}
+
+void ProtobufSourceGenerator::printMoveSemantic()
+{
+    assert(mMessage != nullptr);
+    mPrinter->Print({{"classname", mClassName}},
+                   Templates::MoveConstructorDefinitionTemplate);
+    for (int j = 0; j < mMessage->field_count(); j++) {
+        const FieldDescriptor *field = mMessage->field(j);
         std::string fieldName = field->name();
         auto fieldTypeName = getTypeName(field, mMessage);
         fieldName[0] =  static_cast<char>(::tolower(fieldName[0]));
         if (field->type() == FieldDescriptor::TYPE_MESSAGE
                 && !field->is_map() && !field->is_repeated()) {
-            mPrinter->Print({{"property_name", fieldName}, {"type", fieldTypeName}}, Templates::MessagePropertyInitializerTemplate);
+            mPrinter->Print({{"property_name", fieldName}, {"type", fieldTypeName}}, Templates::MessagePropertyEmptyInitializerTemplate);
+        }
+    }
+    mPrinter->Print("\n{\n");
+
+    Indent();
+    for (int i = 0; i < mMessage->field_count(); i++) {
+        const FieldDescriptor *field = mMessage->field(i);
+        if (isComplexType(field) || field->is_repeated()) {
+            if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
+                printField(mMessage, field, Templates::MoveMessageFieldTemplate);
+            } else {
+                printField(mMessage, field, Templates::MoveComplexFieldTemplate);
+            }
+        } else {
+            if (field->type() != FieldDescriptor::TYPE_ENUM) {
+                printField(mMessage, field, Templates::MoveFieldTemplate);
+            }
+            else {
+                printField(mMessage, field, Templates::EnumMoveFieldTemplate);
+            }
+        }
+    }
+    Outdent();
+    mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
+
+    mPrinter->Print({{"classname", mClassName}},
+                   Templates::MoveAssignmentOperatorDefinitionTemplate);
+    Indent();
+    for (int i = 0; i < mMessage->field_count(); i++) {
+        const FieldDescriptor *field = mMessage->field(i);
+        if (isComplexType(field) || field->is_repeated()) {
+            if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
+                printField(mMessage, field, Templates::MoveMessageFieldTemplate);
+            } else {
+                printField(mMessage, field, Templates::MoveComplexFieldTemplate);
+            }
         } else {
-            mPrinter->Print({{"property_name", fieldName}}, Templates::PropertyInitializerTemplate);
+            if (field->type() != FieldDescriptor::TYPE_ENUM) {
+                printField(mMessage, field, Templates::MoveFieldTemplate);
+            }
+            else {
+                printField(mMessage, field, Templates::EnumMoveFieldTemplate);
+            }
+        }
+    }
+    mPrinter->Print(Templates::AssignmentOperatorReturnTemplate);
+    Outdent();
+    mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
+}
+
+void ProtobufSourceGenerator::printComparisonOperators()
+{
+    assert(mMessage != nullptr);
+    PropertyMap properties;
+    mPrinter->Print({{"classname", mClassName}}, Templates::EqualOperatorDefinitionTemplate);
+
+    bool isFirst = true;
+    if (mMessage->field_count() <= 0) {
+        mPrinter->Print("true");
+    }
+    for (int i = 0; i < mMessage->field_count(); i++) {
+        const FieldDescriptor *field = mMessage->field(i);
+        if (producePropertyMap(mMessage, field, properties)) {
+            if (!isFirst) {
+                mPrinter->Print("\n&& ");
+            } else {
+                Indent();
+                Indent();
+                isFirst = false;
+            }
+            if (field->type() == FieldDescriptor::TYPE_MESSAGE
+                    && !field->is_map() && !field->is_repeated()) {
+                mPrinter->Print(properties, Templates::EqualOperatorMessagePropertyTemplate);
+            } else {
+                mPrinter->Print(properties, Templates::EqualOperatorPropertyTemplate);
+            }
         }
+    }
 
+    //Only if at least one field "copied"
+    if (!isFirst) {
+        Outdent();
+        Outdent();
     }
-    mPrinter->Print(Templates::ConstructorContentTemplate);
+
+    mPrinter->Print(";\n");
+    mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
+
+    mPrinter->Print({{"classname", mClassName}}, Templates::NotEqualOperatorDefinitionTemplate);
+}
+
+void ProtobufSourceGenerator::printGetters()
+{
+    for (int i = 0; i < mMessage->field_count(); i++) {
+        const FieldDescriptor *field = mMessage->field(i);
+        if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
+                printField(mMessage, field, Templates::GetterPrivateMessageDefinitionTemplate);
+                printField(mMessage, field, Templates::GetterMessageDefinitionTemplate);
+        } else {
+            printField(mMessage, field, Templates::GetterDefinitionTemplate);
+        }
+        if (field->is_repeated()) {
+            printField(mMessage, field, Templates::GetterContainerExtraDefinitionTemplate);
+            if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map()
+                    && GeneratorOptions::instance().hasQml()) {
+                printField(mMessage, field, Templates::GetterQmlListDefinitionTemplate);
+            }
+        }
+    }
+    for (int i = 0; i < mMessage->field_count(); i++) {
+        auto field = mMessage->field(i);
+        switch (field->type()) {
+        case FieldDescriptor::TYPE_MESSAGE:
+            if (!field->is_map() && !field->is_repeated()) {
+                printField(mMessage, field, Templates::SetterPrivateTemplateDefinitionMessageType);
+                printField(mMessage, field, Templates::SetterTemplateDefinitionMessageType);
+            } else {
+                printField(mMessage, field, Templates::SetterTemplateDefinitionComplexType);
+            }
+            break;
+        case FieldDescriptor::FieldDescriptor::TYPE_STRING:
+        case FieldDescriptor::FieldDescriptor::TYPE_BYTES:
+            printField(mMessage, field, Templates::SetterTemplateDefinitionComplexType);
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+void ProtobufSourceGenerator::printDestructor()
+{
+    mPrinter->Print({{"classname", mClassName}}, "$classname$::~$classname$()\n"
+                                                 "{}\n\n");
 }

+ 10 - 0
src/generator/protobufsourcegenerator.h

@@ -40,14 +40,24 @@ public:
     void printRegisterBody();
     void printFieldsOrdering();
     void printConstructor();
+    void printCopyFunctionality();
+    void printMoveSemantic();
+    void printComparisonOperators();
+    void printGetters();
+    void printDestructor();
 
     void run() override {
         printDisclaimer();
         printClassHeaderInclude();
         printNamespaces();
+        printDestructor();
         printFieldsOrdering();
         printRegisterBody();
         printConstructor();
+        printCopyFunctionality();
+        printMoveSemantic();
+        printComparisonOperators();
+        printGetters();
         encloseNamespaces();
     }
 };

+ 7 - 0
src/generator/singlefilegenerator.cpp

@@ -152,6 +152,8 @@ bool SingleFileGenerator::GenerateMessages(const ::google::protobuf::FileDescrip
         classGen.printProperties();
         classGen.printPrivate();
         classGen.printClassMembers();
+        classGen.printPublic();
+        classGen.printDestructor();
         classGen.encloseClass();
         classGen.printListType();
         classGen.encloseNamespaces();
@@ -164,7 +166,12 @@ bool SingleFileGenerator::GenerateMessages(const ::google::protobuf::FileDescrip
         srcGen.printNamespaces();
         srcGen.printFieldsOrdering();
         srcGen.printRegisterBody();
+        srcGen.printDestructor();
         srcGen.printConstructor();
+        srcGen.printCopyFunctionality();
+        srcGen.printMoveSemantic();
+        srcGen.printComparisonOperators();
+        srcGen.printGetters();
         srcGen.encloseNamespaces();
 
     });

+ 40 - 17
src/generator/templates.cpp

@@ -30,8 +30,11 @@ using namespace QtProtobuf::generator;
 const char *Templates::DefaultProtobufIncludesTemplate = "#include <QMetaType>\n"
                                                          "#include <QList>\n"
                                                          "#include <QProtobufObject>\n"
+                                                         "#include <QSharedPointer>\n"
+                                                         "\n"
+                                                         "#include <memory>\n"
                                                          "#include <unordered_map>\n"
-                                                         "#include <QSharedPointer>\n\n";
+                                                         "\n";
 
 const char *Templates::QmlProtobufIncludesTemplate = "#include <QtQml/QQmlListProperty>\n"
                                                      "#include <QQmlListPropertyConstructor>\n\n";
@@ -81,7 +84,7 @@ const char *Templates::MessagePropertyTemplate = "Q_PROPERTY($type$ *$property_n
 const char *Templates::QmlListPropertyTemplate = "Q_PROPERTY(QQmlListProperty<$type_nolist$> $property_name$Data READ $property_name$_l NOTIFY $property_name$Changed)\n";
 
 const char *Templates::MemberTemplate = "$type$ m_$property_name$;\n";
-const char *Templates::ComplexMemberTemplate = "$type$ *m_$property_name$;\n";
+const char *Templates::ComplexMemberTemplate = "std::unique_ptr<$type$> m_$property_name$;\n";
 const char *Templates::EnumMemberTemplate = "::$type$ m_$property_name$;\n";
 const char *Templates::PublicBlockTemplate = "\npublic:\n";
 const char *Templates::PrivateBlockTemplate = "\nprivate:\n";
@@ -92,8 +95,10 @@ const char *Templates::ProtoConstructorDefinitionTemplate = "$classname$::$class
 const char *Templates::ConstructorTemplate = "$classname$();\n";
 const char *Templates::QObjectConstructorTemplate = "explicit $classname$(QObject *parent = nullptr);\n";
 const char *Templates::ConstructorHeaderTemplate = "$classname$() {}\n";
-const char *Templates::CopyConstructorTemplate = "$classname$(const $classname$ &other) : QObject() {\n";
-const char *Templates::MoveConstructorTemplate = "$classname$($classname$ &&other) : QObject() {\n";
+const char *Templates::CopyConstructorDeclarationTemplate = "$classname$(const $classname$ &other);\n";
+const char *Templates::MoveConstructorDeclarationTemplate = "$classname$($classname$ &&other);\n";
+const char *Templates::CopyConstructorDefinitionTemplate = "$classname$::$classname$(const $classname$ &other) : QObject()";
+const char *Templates::MoveConstructorDefinitionTemplate = "$classname$::$classname$($classname$ &&other) : QObject()";
 const char *Templates::DeletedCopyConstructorTemplate = "$classname$(const $classname$ &) = delete;\n";
 const char *Templates::DeletedMoveConstructorTemplate = "$classname$($classname$ &&) = delete;\n";
 const char *Templates::CopyFieldTemplate = "set$property_name_cap$(other.m_$property_name$);\n";
@@ -103,38 +108,52 @@ const char *Templates::MoveComplexFieldTemplate = "m_$property_name$ = std::move
 const char *Templates::MoveFieldTemplate = "set$property_name_cap$(std::exchange(other.m_$property_name$, 0));\n"
                                            "other.$property_name$Changed();\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::AssignmentOperatorDeclarationTemplate = "$classname$ &operator =(const $classname$ &other);\n";
+const char *Templates::AssignmentOperatorDefinitionTemplate = "$classname$ &$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"
+
+const char *Templates::MoveAssignmentOperatorDeclarationTemplate = "$classname$ &operator =($classname$ &&other);\n";
+const char *Templates::MoveAssignmentOperatorDefinitionTemplate = "$classname$ &$classname$::operator =($classname$ &&other) {\n";
+
+const char *Templates::EqualOperatorDeclarationTemplate = "bool operator ==(const $classname$ &other) const;\n";
+const char *Templates::EqualOperatorDefinitionTemplate = "bool $classname$::operator ==(const $classname$ &other) const {\n"
                                                "    return ";
 const char *Templates::EqualOperatorPropertyTemplate = "m_$property_name$ == other.m_$property_name$";
 const char *Templates::EqualOperatorMessagePropertyTemplate = "*m_$property_name$ == *other.m_$property_name$";
-const char *Templates::NotEqualOperatorTemplate = "bool operator !=(const $type$ &other) const {\n"
+
+const char *Templates::NotEqualOperatorDeclarationTemplate = "bool operator !=(const $classname$ &other) const;\n";
+const char *Templates::NotEqualOperatorDefinitionTemplate = "bool $classname$::operator !=(const $classname$ &other) const {\n"
                                                   "    return !this->operator ==(other);\n"
                                                   "}\n\n";
 
-const char *Templates::GetterPrivateMessageTemplate = "$type$ *$property_name$_p() const {\n"
-                                        "    return m_$property_name$;\n"
+const char *Templates::GetterPrivateMessageDeclarationTemplate = "$type$ *$property_name$_p() const;\n";
+const char *Templates::GetterPrivateMessageDefinitionTemplate = "$type$ *$classname$::$property_name$_p() const {\n"
+                                        "    return m_$property_name$.get();\n"
                                         "}\n\n";
 
-const char *Templates::GetterMessageTemplate = "$type$ $property_name$() const {\n"
+const char *Templates::GetterMessageDeclarationTemplate = "const $type$ &$property_name$() const;";
+const char *Templates::GetterMessageDefinitionTemplate = "const $type$ &$classname$::$property_name$() const {\n"
                                         "    return *m_$property_name$;\n"
                                         "}\n\n";
 
-const char *Templates::GetterTemplate = "$type$ $property_name$() const {\n"
+const char *Templates::GetterDeclarationTemplate = "$type$ $property_name$() const;\n";
+const char *Templates::GetterDefinitionTemplate = "$type$ $classname$::$property_name$() const {\n"
                                         "    return m_$property_name$;\n"
                                         "}\n\n";
 
-const char *Templates::GetterContainerExtraTemplate = "$type$ &$property_name$() {\n"
+const char *Templates::GetterContainerExtraDeclarationTemplate = "$type$ &$property_name$();\n";
+const char *Templates::GetterContainerExtraDefinitionTemplate = "$type$ &$classname$::$property_name$() {\n"
                                         "    return m_$property_name$;\n"
                                         "}\n\n";
 
-const char *Templates::QmlListGetterTemplate = "QQmlListProperty<$type_nolist$> $property_name$_l() {\n"
+const char *Templates::GetterQmlListDeclarationTemplate = "QQmlListProperty<$type_nolist$> $property_name$_l();\n";
+const char *Templates::GetterQmlListDefinitionTemplate = "QQmlListProperty<$type_nolist$> $classname$::$property_name$_l() {\n"
                                                "    return QtProtobuf::constructQmlListProperty<$type_nolist$>(this, &m_$property_name$);\n"
                                                "}\n\n";
 
-const char *Templates::SetterPrivateTemplateMessageType = "void set$property_name_cap$_p($type$ *$property_name$) {\n"
+const char *Templates::SetterPrivateTemplateDeclarationMessageType = "void set$property_name_cap$_p($type$ *$property_name$);\n";
+const char *Templates::SetterPrivateTemplateDefinitionMessageType = "void $classname$::set$property_name_cap$_p($type$ *$property_name$) {\n"
                                                    "    if ($property_name$ == nullptr) {\n"
                                                    "        *m_$property_name$ = {};\n"
                                                    "        return;\n"
@@ -147,14 +166,16 @@ const char *Templates::SetterPrivateTemplateMessageType = "void set$property_nam
                                                    "    delete $property_name$;\n"
                                                    "}\n\n";
 
-const char *Templates::SetterTemplateMessageType = "void set$property_name_cap$(const $type$ &$property_name$) {\n"
+const char *Templates::SetterTemplateDeclarationMessageType = "void set$property_name_cap$(const $type$ &$property_name$);\n";
+const char *Templates::SetterTemplateDefinitionMessageType = "void $classname$::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";
 
-const char *Templates::SetterTemplateComplexType = "void set$property_name_cap$(const $type$ &$property_name$) {\n"
+const char *Templates::SetterTemplateDeclarationComplexType = "void set$property_name_cap$(const $type$ &$property_name$);\n";
+const char *Templates::SetterTemplateDefinitionComplexType = "void $classname$::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"
@@ -181,7 +202,9 @@ const char *Templates::SimpleBlockEnclosureTemplate = "}\n\n";
 const char *Templates::SemicolonBlockEnclosureTemplate = "};\n";
 const char *Templates::EmptyBlockTemplate = "{}\n\n";
 const char *Templates::PropertyInitializerTemplate = "\n    , m_$property_name$($property_name$)";
+const char *Templates::PropertyEmptyInitializerTemplate = "\n    , m_$property_name$($initializer$)";
 const char *Templates::MessagePropertyInitializerTemplate = "\n    , m_$property_name$(new $type$($property_name$))";
+const char *Templates::MessagePropertyEmptyInitializerTemplate = "\n    , m_$property_name$(new $type$)";
 const char *Templates::ConstructorContentTemplate = "\n{\n}\n";
 
 const char *Templates::DeclareMetaTypeTemplate = "Q_DECLARE_METATYPE($namespaces$::$classname$)\n";

+ 31 - 14
src/generator/templates.h

@@ -62,7 +62,6 @@ public:
     static const char *PropertyTemplate;
     static const char *MessagePropertyTemplate;
     static const char *QmlListPropertyTemplate;
-    static const char *QmlListGetterTemplate;
     static const char *MemberTemplate;
     static const char *ComplexMemberTemplate;
     static const char *EnumMemberTemplate;
@@ -74,8 +73,10 @@ public:
     static const char *ProtoConstructorDefinitionTemplate;
     static const char *ConstructorTemplate;
     static const char *QObjectConstructorTemplate;
-    static const char *CopyConstructorTemplate;
-    static const char *MoveConstructorTemplate;
+    static const char *CopyConstructorDeclarationTemplate;
+    static const char *MoveConstructorDeclarationTemplate;
+    static const char *CopyConstructorDefinitionTemplate;
+    static const char *MoveConstructorDefinitionTemplate;
     static const char *DeletedCopyConstructorTemplate;
     static const char *DeletedMoveConstructorTemplate;
     static const char *CopyFieldTemplate;
@@ -84,21 +85,35 @@ public:
     static const char *MoveComplexFieldTemplate;
     static const char *MoveFieldTemplate;
     static const char *EnumMoveFieldTemplate;
-    static const char *AssignmentOperatorTemplate;
+    static const char *AssignmentOperatorDeclarationTemplate;
+    static const char *AssignmentOperatorDefinitionTemplate;
     static const char *AssignmentOperatorReturnTemplate;
-    static const char *MoveAssignmentOperatorTemplate;
-    static const char *EqualOperatorTemplate;
+    static const char *MoveAssignmentOperatorDeclarationTemplate;
+    static const char *MoveAssignmentOperatorDefinitionTemplate;
+    static const char *EqualOperatorDeclarationTemplate;
+    static const char *EqualOperatorDefinitionTemplate;
     static const char *EqualOperatorPropertyTemplate;
     static const char *EqualOperatorMessagePropertyTemplate;
-    static const char *NotEqualOperatorTemplate;
-    static const char *GetterTemplate;
-    static const char *GetterContainerExtraTemplate;
-    static const char *GetterPrivateMessageTemplate;
-    static const char *GetterMessageTemplate;
+    static const char *NotEqualOperatorDeclarationTemplate;
+    static const char *NotEqualOperatorDefinitionTemplate;
+    static const char *GetterPrivateMessageDeclarationTemplate;
+    static const char *GetterPrivateMessageDefinitionTemplate;
+    static const char *GetterMessageDeclarationTemplate;
+    static const char *GetterMessageDefinitionTemplate;
+    static const char *GetterDeclarationTemplate;
+    static const char *GetterDefinitionTemplate;
+    static const char *GetterContainerExtraDeclarationTemplate;
+    static const char *GetterContainerExtraDefinitionTemplate;
+    static const char *GetterQmlListDeclarationTemplate;
+    static const char *GetterQmlListDefinitionTemplate;
+
+    static const char *SetterPrivateTemplateDeclarationMessageType;
+    static const char *SetterPrivateTemplateDefinitionMessageType;
+    static const char *SetterTemplateDeclarationMessageType;
+    static const char *SetterTemplateDefinitionMessageType;
+    static const char *SetterTemplateDeclarationComplexType;
+    static const char *SetterTemplateDefinitionComplexType;
     static const char *SetterTemplateSimpleType;
-    static const char *SetterTemplateComplexType;
-    static const char *SetterPrivateTemplateMessageType;
-    static const char *SetterTemplateMessageType;
     static const char *SignalsBlockTemplate;
     static const char *SignalTemplate;
     static const char *FieldsOrderingContainerTemplate;
@@ -108,7 +123,9 @@ public:
     static const char *SemicolonBlockEnclosureTemplate;
     static const char *EmptyBlockTemplate;
     static const char *PropertyInitializerTemplate;
+    static const char *PropertyEmptyInitializerTemplate;
     static const char *MessagePropertyInitializerTemplate;
+    static const char *MessagePropertyEmptyInitializerTemplate;
     static const char *ConstructorContentTemplate;
     static const char *DeclareMetaTypeTemplate;
     static const char *DeclareMetaTypeListTemplate;

+ 12 - 0
tests/test_protobuf/proto/sequencetest.proto

@@ -0,0 +1,12 @@
+syntax = "proto3";
+
+package qtprotobufnamespace.tests.sequence;
+
+message TestMessageSequence {
+    TestMessageSequence2 testField = 1;
+}
+
+message TestMessageSequence2 {
+    bool testField = 1;
+}
+

+ 0 - 11
tests/test_protobuf/proto/sequencetest.proto_disabled

@@ -1,11 +0,0 @@
-syntax = "proto3";
-
-package qtprotobufnamespace.tests.sequence;
-
-message TestMessage {
-    TestMessage2 testField = 1;
-}
-
-message TestMessage2 {
-    bool testField = 1;
-}

+ 6 - 0
tests/test_protobuf/simpletest.cpp.inc

@@ -767,5 +767,11 @@ TEST_F(SimpleTest, UnderscoresTest)
     assertMessagePropertyRegistered<CombinedMessageUnderscoreField , sint32>(1, "QtProtobuf::sint32", "_underScoreMessage_Field_");
 }
 
+TEST_F(SimpleTest, SequenceTest)
+{
+    assertMessagePropertyRegistered<sequence::TestMessageSequence, sequence::TestMessageSequence2*>(1, "TestMessageSequence2*", "testField");
+    assertMessagePropertyRegistered<sequence::TestMessageSequence2, bool>(1, "bool", "testField");
+}
+
 } // tests
 } // qtprotobuf

+ 2 - 0
tests/test_protobuf_multifile/simpletest.cpp

@@ -70,6 +70,8 @@
 #include "priormessageunderscorefield.h"
 #include "followingmessageunderscorefield.h"
 #include "combinedmessageunderscorefield.h"
+#include "testmessagesequence.h"
+#include "testmessagesequence2.h"
 
 #include "globalenums.h"