Browse Source

Generator refactoring phase 1

Alexey Edelev 4 years ago
parent
commit
9a821b96db

+ 4 - 2
src/generator/CMakeLists.txt

@@ -19,7 +19,8 @@ file(GLOB SOURCES main.cpp
     clientsourcegenerator.cpp
     singlefilegenerator.cpp
     generatorbase.cpp
-    generatoroptions.cpp)
+    generatoroptions.cpp
+    generatorcommon.cpp)
 
 file(GLOB HEADERS classgeneratorbase.h
     classsourcegeneratorbase.h
@@ -36,7 +37,8 @@ file(GLOB HEADERS classgeneratorbase.h
     utils.h
     singlefilegenerator.h
     generatorbase.h
-    generatoroptions.h)
+    generatoroptions.h
+    generatorcommon.h)
 
 add_executable(${TARGET} ${SOURCES})
 

+ 11 - 31
src/generator/classgeneratorbase.cpp

@@ -33,6 +33,8 @@
 
 #include <set>
 
+#include "generatorcommon.h"
+
 using namespace ::QtProtobuf::generator;
 using namespace ::google::protobuf;
 using namespace ::google::protobuf::io;
@@ -41,7 +43,7 @@ using namespace ::google::protobuf::compiler;
 ClassGeneratorBase::ClassGeneratorBase(const std::string &fullClassName, const std::shared_ptr<::google::protobuf::io::Printer> &printer) :
     mPrinter(printer)
 {
-    utils::split(fullClassName, mNamespaces, '.');
+    mNamespaces = utils::split(fullClassName, '.');
     assert(mNamespaces.size() > 0);
     mClassName = utils::upperCaseName(mNamespaces.back());
     mNamespaces.erase(mNamespaces.end() - 1);
@@ -104,28 +106,22 @@ void ClassGeneratorBase::encloseNamespaces()
     encloseNamespaces(mNamespaces.size());
 }
 
-void ClassGeneratorBase::printPublic()
+void ClassGeneratorBase::printPublicBlock()
 {
     mPrinter->Print(Templates::PublicBlockTemplate);
 }
 
-void ClassGeneratorBase::printPrivate()
+void ClassGeneratorBase::printPrivateBlock()
 {
     mPrinter->Print(Templates::PrivateBlockTemplate);
 }
 
-void ClassGeneratorBase::printMetaTypeDeclaration()
+void ClassGeneratorBase::printSignalsBlock()
 {
-    mPrinter->Print({{"classname", mClassName}, {"namespaces", mNamespacesColonDelimited}},
-                   Templates::DeclareMetaTypeTemplate);
-    mPrinter->Print({{"classname", mClassName}, {"namespaces", mNamespacesColonDelimited}},
-                   Templates::DeclareComplexListTypeTemplate);
-    if (GeneratorOptions::instance().hasQml()) {
-        mPrinter->Print({{"classname", mClassName}, {"namespaces", mNamespacesColonDelimited}},
-                       Templates::DeclareComplexQmlListTypeTemplate);
-    }
+    mPrinter->Print(Templates::SignalsBlockTemplate);
 }
 
+
 bool ClassGeneratorBase::isLocalMessageEnum(const google::protobuf::Descriptor *message,
                                             const ::google::protobuf::FieldDescriptor *field)
 {
@@ -231,7 +227,7 @@ template<typename T>
 std::string ClassGeneratorBase::getNamespacesList(const T *message, std::vector<std::string> &container, const std::string &localNamespace)
 {
     std::string result;
-    utils::split(std::string(message->full_name()), container, '.');
+    container = utils::split(std::string(message->full_name()), '.');
 
     if (container.size() > 1) {
         //delete type name -> only namespace stays
@@ -333,9 +329,6 @@ bool ClassGeneratorBase::producePropertyMap(const google::protobuf::Descriptor *
         return false;
     }
 
-    std::string typeNameLower(typeName);
-    utils::tolower(typeNameLower);
-
     std::string typeNameNoList = typeName;
     if (field->is_repeated() && !field->is_map()) {
         if(field->type() == FieldDescriptor::TYPE_MESSAGE
@@ -370,7 +363,6 @@ bool ClassGeneratorBase::producePropertyMap(const google::protobuf::Descriptor *
 
     propertyMap = {{"type", typeName},
                    {"classname", utils::upperCaseName(message->name())},
-                   {"type_lower", typeNameLower},
                    {"property_name", fieldName},
                    {"property_name_cap", capProperty},
                    {"type_nolist", typeNameNoList},
@@ -419,8 +411,7 @@ void ClassGeneratorBase::printInclude(const google::protobuf::Descriptor *messag
             std::string outFileBasename = "";
             std::string fieldPackage = field->message_type()->file()->package();
             if (fieldPackage != message->file()->package()) {
-                std::vector<std::string> packages;
-                utils::split(fieldPackage, packages, '.');
+                std::vector<std::string> packages = utils::split(fieldPackage, '.');
                 for (auto package : packages) {
                     outFileBasename += package + "/";
                 }
@@ -447,8 +438,7 @@ void ClassGeneratorBase::printInclude(const google::protobuf::Descriptor *messag
         } else if (enumVisibily == NEIGHBOUR_ENUM) {
             includeTemplate = Templates::InternalIncludeTemplate;
             std::string fullEnumName = field->enum_type()->full_name();
-            std::vector<std::string> fullEnumNameParts;
-            utils::split(fullEnumName, fullEnumNameParts, '.');
+            std::vector<std::string> fullEnumNameParts = utils::split(fullEnumName, '.');
             std::string enumTypeOwner = fullEnumNameParts.at(fullEnumNameParts.size() - 2);
             utils::tolower(enumTypeOwner);
             newInclude = enumTypeOwner;
@@ -466,13 +456,3 @@ void ClassGeneratorBase::printInclude(const google::protobuf::Descriptor *messag
         existingIncludes.insert(newInclude);
     }
 }
-
-bool ClassGeneratorBase::hasQmlAlias(const ::google::protobuf::FieldDescriptor *field)
-{
-    return !field->is_map() && !field->is_repeated()
-            && (field->type() == FieldDescriptor::TYPE_INT32
-                || field->type() == FieldDescriptor::TYPE_SFIXED32
-                || field->type() == FieldDescriptor::TYPE_FIXED32)
-            && GeneratorOptions::instance().hasQml();
-}
-

+ 4 - 5
src/generator/classgeneratorbase.h

@@ -77,10 +77,10 @@ public:
     void printNamespaces();
     void printNamespaces(const std::vector<std::string> &namespaces);
     void printClassDeclaration();
-    void printPublic();
-    void printPrivate();
+    void printPublicBlock();
+    void printPrivateBlock();
+    void printSignalsBlock();
     void encloseClass();
-    void printMetaTypeDeclaration();
     void encloseNamespaces();
     void encloseNamespaces(int count);
     void printInclude(const google::protobuf::Descriptor *message, const google::protobuf::FieldDescriptor *field, std::set<std::string> &existingIncludes);
@@ -96,7 +96,7 @@ public:
             return;
         }
 
-        printPublic();
+        printPublicBlock();
 
         Indent();
         for (int i = 0; i < message->enum_type_count(); i++) {
@@ -172,7 +172,6 @@ public:
     template<typename T>
     static std::string getNamespacesList(const T *message, std::vector<std::string> &container, const std::string &localNamespace);
     static EnumVisibility getEnumVisibility(const ::google::protobuf::FieldDescriptor *field, const ::google::protobuf::Descriptor *messageFor);
-    static bool hasQmlAlias(const ::google::protobuf::FieldDescriptor *field);
     void getMethodParameters(const ::google::protobuf::MethodDescriptor *method, std::map<std::string, std::string> &parameters);
 };
 

+ 1 - 1
src/generator/clientgenerator.h

@@ -59,7 +59,7 @@ public:
         printClientIncludes();
         printNamespaces();
         printClientClass();
-        printPublic();
+        printPublicBlock();
         printConstructor();
         printClientMethodsDeclaration();
         encloseClass();

+ 6 - 4
src/generator/enumsgenerator.cpp

@@ -35,29 +35,31 @@ using namespace ::google::protobuf::compiler;
 EnumsGenerator::EnumsGenerator(const EnumDescriptor *enumDesctiptor, const std::shared_ptr<io::ZeroCopyOutputStream> &out) :
     ClassGeneratorBase(enumDesctiptor->full_name() + Templates::EnumClassSuffix, out)
   , mEnumDescriptor(enumDesctiptor)
+  , mTypeMap(common::produceEnumTypeMap(enumDesctiptor, nullptr))
 {}
 
 
 EnumsGenerator::EnumsGenerator(const EnumDescriptor *enumDesctiptor, const std::shared_ptr<::google::protobuf::io::Printer> &printer) :
     ClassGeneratorBase(enumDesctiptor->full_name() + Templates::EnumClassSuffix, printer)
   , mEnumDescriptor(enumDesctiptor)
+  , mTypeMap(common::produceEnumTypeMap(enumDesctiptor, nullptr))
 {}
 
 void EnumsGenerator::startEnum()
 {
     printNamespaces(mNamespaces);
     printEnumClass();
-    printPublic();
+    printPublicBlock();
     Indent();
     mPrinter->Print({{"classname", mClassName}}, Templates::ManualRegistrationDeclaration);
     Outdent();
-    printPrivate();
+    printPrivateBlock();
     printConstructor();
 }
 
 void EnumsGenerator::printEnum()
 {
-    printPublic();
+    printPublicBlock();
 
     Indent();
     mPrinter->Print({{"enum", mEnumDescriptor->name()}}, Templates::EnumDefinitionTemplate);
@@ -94,7 +96,7 @@ void EnumsGenerator::run()
 
 void EnumsGenerator::printMetatype()
 {
-    mPrinter->Print({{"classname", mEnumDescriptor->name()}, {"namespaces", mNamespacesColonDelimited + "::" + mClassName}},
+    mPrinter->Print(mTypeMap,
                    Templates::DeclareMetaTypeListTemplate);
 }
 

+ 3 - 0
src/generator/enumsgenerator.h

@@ -27,6 +27,7 @@
 
 #include "classgeneratorbase.h"
 #include "utils.h"
+#include "generatorcommon.h"
 
 namespace google {
 namespace protobuf {
@@ -56,6 +57,8 @@ public:
     void printMetatype();
     void printEnumClass();
     void printConstructor();
+private:
+    TypeMap mTypeMap;
 };
 
 } //namespace generator

+ 1 - 2
src/generator/generatorbase.cpp

@@ -73,8 +73,7 @@ bool GeneratorBase::GenerateAll(const std::vector<const FileDescriptor *> &files
 
 std::string GeneratorBase::generateBaseName(const ::google::protobuf::FileDescriptor *file, std::string name)
 {
-    std::vector<std::string> packages;
-    utils::split(file->package(), packages, '.');
+    std::vector<std::string> packages = utils::split(file->package(), '.');
     std::string outFileBasename = "";
     if (GeneratorOptions::instance().isFolder()) {
         for (auto package : packages) {

+ 337 - 0
src/generator/generatorcommon.cpp

@@ -0,0 +1,337 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 Alexey Edelev <semlanik@gmail.com>
+ *
+ * This file is part of QtProtobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "generatorcommon.h"
+#include "generatoroptions.h"
+
+#include "templates.h"
+#include <assert.h>
+
+using namespace ::QtProtobuf::generator;
+using namespace ::google::protobuf;
+
+std::string common::getNamespacesString(const std::vector<std::string> &namespacesList, const std::string &separator)
+{
+    std::string namespaces;
+    for(auto namespacePart : namespacesList) {
+        namespaces += namespacePart + separator;
+    }
+
+    if (!namespaces.empty()) {
+        namespaces.resize(namespaces.size() - separator.size());
+    }
+    return namespaces;
+}
+
+std::string common::getScopeNamespacesString(std::string original, const std::string &scope)
+{
+    if (scope.empty()) {
+        return original;
+    }
+
+    if (original == scope) {
+        return "";
+    }
+
+    if (original.find(scope + "::") == 0) {
+        original = original.replace(0, scope.size() + 2, ""); //Remove trailing :: as well
+    }
+    return original;
+}
+
+TypeMap common::produceMessageTypeMap(const ::Descriptor *type, const Descriptor *scope)
+{
+    std::vector<std::string> namespaceList = getNamespaces(type);
+    std::string namespaces = getNamespacesString(namespaceList, "::");
+    std::string scopeNamespaces = getScopeNamespacesString(namespaces, getNamespacesString(getNamespaces(scope), "::"));
+    std::string qmlPackage = getNamespacesString(namespaceList, ".");
+
+    std::string name = utils::upperCaseName(type->name());
+    std::string fullName = namespaces.empty() ? name : (namespaces + "::" + name);
+    std::string scopeName = scopeNamespaces.empty() ? name : (scopeNamespaces + "::" + name);
+
+    std::string listName = name + Templates::ListSuffix;
+    std::string fullListName = namespaces.empty() ? listName : (namespaces + "::" + listName);
+    std::string scopeListName = scopeNamespaces.empty() ? listName : (scopeNamespaces + "::" + listName);
+
+    return {
+        {"type", name},
+        {"full_type", fullName},
+        {"scope_type", scopeName},
+        {"list_type", listName},
+        {"full_list_type", fullListName},
+        {"scope_list_type", scopeListName},
+        {"namespaces", namespaces},
+        {"qml_package", qmlPackage},
+        {"property_type", fullName},
+        {"property_list_type", fullListName},
+        {"getter_type", scopeName},
+        {"setter_type", scopeName}
+    };
+}
+
+TypeMap common::produceEnumTypeMap(const EnumDescriptor *type, const Descriptor *scope)
+{
+    EnumVisibility visibility = enumVisibility(type, scope);
+    std::vector<std::string> namespaceList = getNamespaces(type);
+    if(visibility == GLOBAL_ENUM) {
+        namespaceList.push_back(type->name() + Templates::EnumClassSuffix);//Global enums are stored in helper Gadget
+    }
+
+    std::string namespaces = getNamespacesString(namespaceList, "::");
+    std::string scopeNamespaces = getScopeNamespacesString(namespaces, getNamespacesString(getNamespaces(scope), "::"));
+    std::string qmlPackage = getNamespacesString(namespaceList, ".");
+
+    std::string name = type->name();
+    std::string fullName = namespaces.empty() ? name : (namespaces + "::" + name);
+    std::string scopeName = scopeNamespaces.empty() ? name : (scopeNamespaces + "::" + name);
+
+    std::string listName = name + Templates::ListSuffix;
+    std::string fullListName = namespaces.empty() ? listName : (namespaces + "::" + listName);
+    std::string scopeListName = scopeNamespaces.empty() ? listName: (scopeNamespaces + "::" + listName);
+
+    std::string propertyType = fullName;
+    if (visibility == LOCAL_ENUM) {
+        //Note: For local enum classes it's impossible to use class name space in Q_PROPERTY
+        //declaration. So please avoid addition of namespaces in line bellow
+        propertyType = name;
+    }
+
+    return {
+        {"type", name},
+        {"full_type", fullName},
+        {"scope_type", scopeName},
+        {"list_type", listName},
+        {"full_list_type", fullListName},
+        {"scope_list_type", scopeListName},
+        {"namespaces", namespaces},
+        {"qml_package", qmlPackage},
+        {"property_type", propertyType},
+        {"property_list_type", fullListName},
+        {"getter_type", scopeName},
+        {"setter_type", scopeName}
+    };
+}
+
+TypeMap common::produceSimpleTypeMap(FieldDescriptor::Type type)
+{
+    std::string namespaces;
+    if (type != FieldDescriptor::TYPE_STRING
+            && type != FieldDescriptor::TYPE_BYTES
+            && type != FieldDescriptor::TYPE_BOOL
+            && type != FieldDescriptor::TYPE_FLOAT
+            && type != FieldDescriptor::TYPE_DOUBLE) {
+        namespaces = Templates::QtProtobufNamespace;
+    }
+
+    std::string name;
+    std::string qmlPackage = Templates::QtProtobufNamespace;
+
+    auto it = Templates::TypeReflection.find(type);
+    if (it != std::end(Templates::TypeReflection)) {
+        name = it->second;
+    } else {
+        assert(name.empty());
+    }
+
+    std::string fullName = namespaces.empty() ? name : (namespaces + "::" + name);
+    std::string scopeName = fullName;
+
+    std::string listName = name + "List";
+    if (type == FieldDescriptor::TYPE_FLOAT
+            || type == FieldDescriptor::TYPE_DOUBLE
+            || type == FieldDescriptor::TYPE_BOOL) {
+        listName = utils::upperCaseName(name) + "List";
+    }
+
+    std::string fullListName = listName;
+    if (type != FieldDescriptor::TYPE_STRING
+            && type != FieldDescriptor::TYPE_BYTES) {
+        fullListName = std::string(Templates::QtProtobufNamespace) + "::" + listName;
+    }
+
+    std::string scopeListName = fullListName;
+
+    std::string qmlAliasType = fullName;
+    switch (type) {
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_SFIXED32:
+        qmlAliasType = "int";
+        break;
+    case FieldDescriptor::TYPE_FIXED32:
+        qmlAliasType = "unsigned int";
+        break;
+    default:
+        //Do nothing
+        break;
+    }
+
+    std::string getterType = fullName;
+    if (type == FieldDescriptor::TYPE_INT32
+            || type == FieldDescriptor::TYPE_FIXED32
+            || type == FieldDescriptor::TYPE_SFIXED32
+            || type == FieldDescriptor::TYPE_INT64
+            || type == FieldDescriptor::TYPE_FIXED64
+            || type == FieldDescriptor::TYPE_SFIXED64) {
+        getterType = "const " + getterType;
+    }
+
+    return {{"type", name},
+        {"full_type", fullName},
+        {"scope_type", scopeName},
+        {"list_type", listName},
+        {"full_list_type", fullListName},
+        {"scope_list_type", scopeListName},
+        {"namespaces", namespaces},
+        {"qml_package", qmlPackage},
+        {"property_type", fullName},
+        {"qml_alias_type", qmlAliasType},
+        {"property_list_type", fullListName},
+        {"getter_type", getterType},
+        {"setter_type", fullName}
+    };
+}
+
+TypeMap common::produceTypeMap(const FieldDescriptor *field, const Descriptor *scope)
+{
+    TypeMap typeMap;
+
+    assert(field != nullptr);
+    std::string namespaceTypeName;
+    std::vector<std::string> typeNamespace;
+
+    switch(field->type()) {
+    case FieldDescriptor::TYPE_MESSAGE:
+        typeMap = produceMessageTypeMap(field->message_type(), scope);
+        break;
+    case FieldDescriptor::TYPE_ENUM:
+        typeMap = produceEnumTypeMap(field->enum_type(), scope);
+        break;
+    default:
+        typeMap = produceSimpleTypeMap(field->type());
+        break;
+    }
+
+    return typeMap;
+}
+
+PropertyMap common::producePropertyMap(const FieldDescriptor *field, const Descriptor *scope)
+{
+    assert(field != nullptr);
+
+    PropertyMap propertyMap = produceTypeMap(field, scope);
+
+    std::string scriptable = "true";
+    if (!field->is_map() && !field->is_repeated() && (field->type() == FieldDescriptor::TYPE_INT64
+                                                      || field->type() == FieldDescriptor::TYPE_SINT64
+                                                      || field->type() == FieldDescriptor::TYPE_FIXED64
+                                                      || field->type() == FieldDescriptor::TYPE_SFIXED64)) {
+        scriptable = "false";
+    }
+
+    std::string propertyName =  qualifiedName(utils::lowerCaseName(field->camelcase_name()));
+    std::string propertyNameCap = utils::upperCaseName(propertyName);
+
+    propertyMap["property_name"] = propertyName;
+    propertyMap["property_name_cap"] = propertyNameCap;
+    propertyMap["scriptable"] = scriptable;
+
+    propertyMap["key_type"] = "";
+    propertyMap["value_type"] = "";
+    propertyMap["classname"] = scope != nullptr ? utils::upperCaseName(scope->name()) : "";
+
+    if (field->is_map()) {
+        const Descriptor *type = field->message_type();
+        auto keyMap = common::producePropertyMap(type->field(0), scope);
+        auto valueMap = common::producePropertyMap(type->field(1), scope);
+        propertyMap["key_type"] = keyMap["scope_type"];
+        propertyMap["value_type"] = valueMap["scope_type"];
+        propertyMap["value_list_type"] = valueMap["scope_list_type"];
+    } else if (field->is_repeated()) {
+        propertyMap["getter_type"] = propertyMap["scope_list_type"];
+        propertyMap["setter_type"] = propertyMap["scope_list_type"];
+    }
+
+    return propertyMap;
+}
+
+std::string common::qualifiedName(const std::string &name)
+{
+    std::string fieldName(name);
+    const std::vector<std::string> &searchExeptions = Templates::ListOfQmlExeptions;
+
+    auto searchResult = std::find(searchExeptions.begin(), searchExeptions.end(), fieldName);
+    if (searchResult != searchExeptions.end()) {
+        return fieldName.append(Templates::ProtoSufix);
+    }
+    return fieldName;
+}
+
+bool common::isLocalEnum(const EnumDescriptor *type, const google::protobuf::Descriptor *scope)
+{
+    if (scope == nullptr) {
+        return false;
+    }
+
+    assert(type != nullptr);
+    for (int i = 0; i < scope->enum_type_count(); i++) {
+        const auto scopeEnum = scope->enum_type(i);
+        if (scopeEnum && scopeEnum->full_name() == type->full_name()) {
+            return true;
+        }
+    }
+    return false;
+}
+
+common::EnumVisibility common::enumVisibility(const EnumDescriptor *type, const Descriptor *scope)
+{
+    assert(type != nullptr);
+
+    if (isLocalEnum(type, scope)) {
+        return LOCAL_ENUM;
+    }
+
+    const FileDescriptor *typeFile = type->file();
+
+    for (int i = 0; i < typeFile->message_type_count(); i++) {
+        const Descriptor *msg = typeFile->message_type(i);
+        for (int j = 0; j < msg->enum_type_count(); j++) {
+            if (type->full_name() == msg->enum_type(j)->full_name()) {
+                return NEIGHBOR_ENUM;
+            }
+        }
+    }
+
+    return GLOBAL_ENUM;
+}
+
+bool common::hasQmlAlias(const ::google::protobuf::FieldDescriptor *field)
+{
+    return !field->is_map() && !field->is_repeated()
+            && (field->type() == FieldDescriptor::TYPE_INT32
+                || field->type() == FieldDescriptor::TYPE_SFIXED32
+                || field->type() == FieldDescriptor::TYPE_FIXED32)
+            && GeneratorOptions::instance().hasQml();
+}

+ 75 - 0
src/generator/generatorcommon.h

@@ -0,0 +1,75 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2020 Alexey Edelev <semlanik@gmail.com>
+ *
+ * This file is part of QtProtobuf project https://git.semlanik.org/semlanik/qtprotobuf
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and
+ * to permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+ * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <vector>
+#include <map>
+#include <string>
+
+#include "utils.h"
+
+#include <google/protobuf/descriptor.h>
+
+namespace QtProtobuf {
+namespace generator {
+
+using TypeMap = std::map<std::string, std::string>;
+using PropertyMap = std::map<std::string, std::string>;
+struct common {
+    enum EnumVisibility {
+        GLOBAL_ENUM,
+        LOCAL_ENUM,
+        NEIGHBOR_ENUM
+    };
+
+    template <typename T>
+    static std::vector<std::string> getNamespaces(const T *type) {
+        if (type == nullptr) {
+            return {};
+        }
+
+        std::vector<std::string> namespacesList = utils::split(type->full_name(), '.');
+        if (!namespacesList.empty()) {
+            namespacesList.pop_back(); //Remove name
+        }
+        return namespacesList;
+    }
+
+    static std::string getNamespacesString(const std::vector<std::string> &namespacesList, const std::string &separator);
+    static std::string getScopeNamespacesString(std::string original, const std::string &scope);
+    static TypeMap produceMessageTypeMap(const ::google::protobuf::Descriptor *type, const ::google::protobuf::Descriptor *scope);
+    static TypeMap produceEnumTypeMap(const ::google::protobuf::EnumDescriptor *type, const ::google::protobuf::Descriptor *scope);
+    static TypeMap produceSimpleTypeMap(::google::protobuf::FieldDescriptor::Type type);
+    static TypeMap produceTypeMap(const ::google::protobuf::FieldDescriptor *field, const ::google::protobuf::Descriptor *scope);
+    static PropertyMap producePropertyMap(const ::google::protobuf::FieldDescriptor *field, const ::google::protobuf::Descriptor *scope);
+    static std::string qualifiedName(const std::string &name);
+    static bool isLocalEnum(const ::google::protobuf::EnumDescriptor *type, const google::protobuf::Descriptor *scope);
+    static EnumVisibility enumVisibility(const ::google::protobuf::EnumDescriptor *type, const ::google::protobuf::Descriptor *scope);
+    static bool hasQmlAlias(const ::google::protobuf::FieldDescriptor *field);
+};
+
+}
+}

+ 1 - 2
src/generator/generatoroptions.cpp

@@ -46,8 +46,7 @@ GeneratorOptions::GeneratorOptions() : mIsMulti(false)
 
 void GeneratorOptions::parseFromEnv(const std::string &options)
 {
-    std::vector<std::string> optionsList;
-    utils::split(options, optionsList, ':');
+    std::vector<std::string> optionsList = utils::split(options, ':');
     for (auto option : optionsList) {
         QT_PROTOBUF_DEBUG("option: " << option);
         if (option.compare(MultifileBuildOption) == 0) {

+ 127 - 157
src/generator/protobufclassgenerator.cpp

@@ -26,6 +26,7 @@
 #include "protobufclassgenerator.h"
 #include "utils.h"
 #include "generatoroptions.h"
+#include "generatorcommon.h"
 
 #include <iostream>
 #include <google/protobuf/descriptor.h>
@@ -40,12 +41,14 @@ using namespace ::google::protobuf::compiler;
 ProtobufClassGenerator::ProtobufClassGenerator(const Descriptor *message, const std::shared_ptr<::google::protobuf::io::ZeroCopyOutputStream> &out)
     : ClassGeneratorBase(message->full_name(), out)
     , mMessage(message)
+    , mTypeMap(common::produceMessageTypeMap(message, nullptr))
 {
 }
 
 ProtobufClassGenerator::ProtobufClassGenerator(const ::google::protobuf::Descriptor *message, const std::shared_ptr<::google::protobuf::io::Printer> &printer)
     : ClassGeneratorBase(message->full_name(), printer)
     , mMessage(message)
+    , mTypeMap(common::produceMessageTypeMap(message, nullptr))
 {
 
 }
@@ -73,7 +76,6 @@ void ProtobufClassGenerator::printMoveSemantic()
 void ProtobufClassGenerator::printComparisonOperators()
 {
     assert(mMessage != nullptr);
-    PropertyMap properties;
     mPrinter->Print({{"classname", mClassName}}, Templates::EqualOperatorDeclarationTemplate);
 
     mPrinter->Print({{"classname", mClassName}}, Templates::NotEqualOperatorDeclarationTemplate);
@@ -94,63 +96,33 @@ void ProtobufClassGenerator::printIncludes()
     }
 }
 
-bool ProtobufClassGenerator::isListType(const FieldDescriptor *field)
+void ProtobufClassGenerator::printConstructors()
 {
-    assert(field != nullptr);
-    return field && field->is_repeated()
-            && field->type() == FieldDescriptor::TYPE_MESSAGE;
+    for (int i = 0; i <= mMessage->field_count(); i++) {
+        printConstructor(i);
+    }
 }
 
-void ProtobufClassGenerator::printConstructor()
+void ProtobufClassGenerator::printConstructor(int fieldCount)
 {
     std::vector<std::string> parameterList;
-    for (int i = 0; i < mMessage->field_count(); i++) {
+    mPrinter->Print({{"classname", mClassName}}, Templates::ProtoConstructorBeginTemplate);
+    for (int i = 0; i < fieldCount; i++) {
         const FieldDescriptor *field = mMessage->field(i);
-        std::string fieldTypeName = getTypeName(field, mMessage);
-        std::string fieldName = utils::lowerCaseName(field->name());
-        fieldName = qualifiedName(fieldName);
-
-        if (field->is_repeated() || field->is_map()) {
-            parameterList.push_back("const " + fieldTypeName + " &" + fieldName);
-        } else {
-            switch (field->type()) {
-            case FieldDescriptor::TYPE_DOUBLE:
-            case FieldDescriptor::TYPE_FLOAT:
-                parameterList.push_back(fieldTypeName + " " + fieldName);
-                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:
-                parameterList.push_back(fieldTypeName + " " + fieldName);
-                break;
-            case FieldDescriptor::TYPE_BOOL:
-                parameterList.push_back(fieldTypeName + " " + fieldName);
-                break;
-            case FieldDescriptor::TYPE_BYTES:
-            case FieldDescriptor::TYPE_STRING:
-            case FieldDescriptor::TYPE_MESSAGE:
-                parameterList.push_back("const " + fieldTypeName + " &" + fieldName);
-                break;
-            default:
-                parameterList.push_back(fieldTypeName + " " + fieldName);
-                break;
-            }
+        const char *parameterTemplate = Templates::ConstructorParameterTemplate;
+        FieldDescriptor::Type fieldType = field->type();
+        if (field->is_repeated() && !field->is_map()) {
+            parameterTemplate = Templates::ConstructorRepeatedParameterTemplate;
+        } else if(fieldType == FieldDescriptor::TYPE_BYTES
+                  || fieldType == FieldDescriptor::TYPE_STRING
+                  || fieldType == FieldDescriptor::TYPE_MESSAGE
+                  || field->is_map()) {
+            parameterTemplate = Templates::ConstructorMessageParameterTemplate;
         }
+        mPrinter->Print(common::producePropertyMap(field, mMessage), parameterTemplate);
     }
 
-    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({{"classname", mClassName}}, Templates::ProtoConstructorEndTemplate);
     mPrinter->Print("\n");
 }
 
@@ -158,65 +130,42 @@ void ProtobufClassGenerator::printMaps()
 {
     Indent();
     for (int i = 0; i < mMessage->field_count(); i++) {
-        const FieldDescriptor *field = mMessage->field(i);
-
+        const FieldDescriptor *field = mMessage->field(i);        
         if (field->is_map()) {
-            std::string keyType = getTypeName(field->message_type()->field(0), mMessage);
-            std::string valueType = getTypeName(field->message_type()->field(1), mMessage);
-            const char *mapTemplate = Templates::MapTypeUsingTemplate;
-
-            if (field->message_type()->field(1)->type() == FieldDescriptor::TYPE_MESSAGE) {
-                mapTemplate = Templates::MessageMapTypeUsingTemplate;
-            }
-
-            mPrinter->Print({{"classname", utils::upperCaseName(field->message_type()->name())},
-                             {"key", keyType},
-                             {"value", valueType}}, mapTemplate);
+            const Descriptor *type = field->message_type();
+            const char *mapTemplate = type->field(1)->type() == FieldDescriptor::TYPE_MESSAGE ? Templates::MessageMapTypeUsingTemplate : Templates::MapTypeUsingTemplate;
+            mPrinter->Print(common::producePropertyMap(field, mMessage), mapTemplate);
         }
     }
     Outdent();
 }
 
-void ProtobufClassGenerator::printLocalEnumsMetaTypesDeclaration()
+void ProtobufClassGenerator::printMetaTypesDeclaration()
 {
-    for (int i = 0; i < mMessage->field_count(); i++) {
-        const FieldDescriptor *field = mMessage->field(i);
-        if (field == nullptr || field->enum_type() == nullptr)
-            continue;
+    mPrinter->Print(mTypeMap,
+                   Templates::DeclareMetaTypeTemplate);
+    mPrinter->Print(mTypeMap,
+                   Templates::DeclareComplexListTypeTemplate);
 
-        if (field->type() == FieldDescriptor::TYPE_ENUM
-                && isLocalMessageEnum(mMessage, field)) {
-            mPrinter->Print({{"classname", mClassName + "::" + field->enum_type()->name() + Templates::ListSuffix},
-                             {"namespaces", mNamespacesColonDelimited}}, Templates::DeclareMetaTypeTemplate);
-        }
+    if (GeneratorOptions::instance().hasQml()) {
+        mPrinter->Print(mTypeMap,
+                        Templates::DeclareComplexQmlListTypeTemplate);
     }
-}
 
-void ProtobufClassGenerator::printMapsMetaTypesDeclaration()
-{
     for (int i = 0; i < mMessage->field_count(); i++) {
         const FieldDescriptor *field = mMessage->field(i);
-        if (field->is_map()) {
-            std::string keyType = getTypeName(field->message_type()->field(0), nullptr);
-            utils::replace(keyType, "::", "_");
-
-            std::string valueType = "";
-            if (field->message_type()->field(1)->type() == FieldDescriptor::TYPE_MESSAGE) {
-                valueType = field->message_type()->field(1)->message_type()->full_name();
-                utils::replace(valueType, ".", "_");
-            } else if (field->message_type()->field(1)->type() == FieldDescriptor::TYPE_ENUM){
-                valueType = field->message_type()->field(1)->enum_type()->full_name();
-                utils::replace(valueType, ".", "_");
-            } else {
-                valueType = getTypeName(field->message_type()->field(0), nullptr);
-                utils::replace(valueType, "::", "_");
-            }
+        auto fieldMap = common::producePropertyMap(field, nullptr);
+        if (field->type() == FieldDescriptor::TYPE_ENUM
+                && common::isLocalEnum(field->enum_type(), mMessage)) {
+            mPrinter->Print(fieldMap, Templates::DeclareMetaTypeTemplate);
+        } else if (field->is_map()) {
+            fieldMap["key_type_underscore"] = fieldMap["key_type"];
+            utils::replace(fieldMap["key_type_underscore"], "::", "_");
 
+            fieldMap["value_type_underscore"] = fieldMap["key_type"];
+            utils::replace(fieldMap["value_type_underscore"], "::", "_");
 
-            mPrinter->Print({{"classname", field->message_type()->name()},
-                             {"key", keyType},
-                             {"value", valueType},
-                             {"namespaces", mNamespacesColonDelimited + "::" + mClassName}}, Templates::DeclareMetaTypeMapTemplate);
+            mPrinter->Print(fieldMap, Templates::DeclareMetaTypeMapTemplate);
         }
     }
 }
@@ -226,15 +175,18 @@ void ProtobufClassGenerator::printProperties()
     assert(mMessage != nullptr);
     //private section
     Indent();
+
     for (int i = 0; i < mMessage->field_count(); i++) {
         const FieldDescriptor *field = mMessage->field(i);
         const char *propertyTemplate = Templates::PropertyTemplate;
         if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
             propertyTemplate = Templates::MessagePropertyTemplate;
-        } else if (hasQmlAlias(field)) {
+        } else if (common::hasQmlAlias(field)) {
             propertyTemplate = Templates::NonScriptablePropertyTemplate;
+        } else if (field->is_repeated() && !field->is_map()) {
+            propertyTemplate = Templates::RepeatedPropertyTemplate;
         }
-        printField(mMessage, field, propertyTemplate);
+        mPrinter->Print(common::producePropertyMap(field, mMessage), propertyTemplate);
     }
 
     //Generate extra QmlListProperty that is mapped to list
@@ -242,93 +194,128 @@ 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(mMessage, field, Templates::QmlListPropertyTemplate);
-        } else if (hasQmlAlias(field)) {
-            printField(mMessage, field, Templates::NonScriptableAliasPropertyTemplate);
+            mPrinter->Print(common::producePropertyMap(field, mMessage), Templates::QmlListPropertyTemplate);
+        } else if (common::hasQmlAlias(field)) {
+            mPrinter->Print(common::producePropertyMap(field, mMessage), Templates::NonScriptableAliasPropertyTemplate);
         }
     }
 
     Outdent();
+}
 
-    printQEnums(mMessage);
-
-    //public section
-    printPublic();
-    printMaps();
-
-    //Body
+void ProtobufClassGenerator::printGetters()
+{
     Indent();
-    printConstructor();
-    printCopyFunctionality();
-    printMoveSemantic();
-    printComparisonOperators();
-
     for (int i = 0; i < mMessage->field_count(); i++) {
         const FieldDescriptor *field = mMessage->field(i);
         printComments(field);
         mPrinter->Print("\n");
+
+        PropertyMap propertyMap = common::producePropertyMap(field, mMessage);
         if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
-            printField(mMessage, field, Templates::GetterPrivateMessageDeclarationTemplate);
-            printField(mMessage, field, Templates::GetterMessageDeclarationTemplate);
+            mPrinter->Print(propertyMap, Templates::GetterPrivateMessageDeclarationTemplate);
+            mPrinter->Print(propertyMap, Templates::GetterMessageDeclarationTemplate);
         } else {
-            printField(mMessage, field, Templates::GetterTemplate);
+            mPrinter->Print(propertyMap, Templates::GetterTemplate);
         }
+
         if (field->is_repeated()) {
-            printField(mMessage, field, Templates::GetterContainerExtraDeclarationTemplate);
+            mPrinter->Print(propertyMap, Templates::GetterContainerExtraTemplate);
             if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map()
                     && GeneratorOptions::instance().hasQml()) {
-                printField(mMessage, field, Templates::GetterQmlListDeclarationTemplate);
+                mPrinter->Print(propertyMap, Templates::GetterQmlListDeclarationTemplate);
             }
         }
     }
+    Outdent();
+}
 
+void ProtobufClassGenerator::printSetters()
+{
+    Indent();
     for (int i = 0; i < mMessage->field_count(); i++) {
         auto field = mMessage->field(i);
+        PropertyMap propertyMap = common::producePropertyMap(field, mMessage);
         switch (field->type()) {
         case FieldDescriptor::TYPE_MESSAGE:
             if (!field->is_map() && !field->is_repeated()) {
-                printField(mMessage, field, Templates::SetterPrivateTemplateDeclarationMessageType);
-                printField(mMessage, field, Templates::SetterTemplateDeclarationMessageType);
+                mPrinter->Print(propertyMap, Templates::SetterPrivateTemplateDeclarationMessageType);
+                mPrinter->Print(propertyMap, Templates::SetterTemplateDeclarationMessageType);
             } else {
-                printField(mMessage, field, Templates::SetterTemplateDeclarationComplexType);
+                mPrinter->Print(propertyMap, Templates::SetterTemplateDeclarationComplexType);
             }
             break;
         case FieldDescriptor::FieldDescriptor::TYPE_STRING:
         case FieldDescriptor::FieldDescriptor::TYPE_BYTES:
-            printField(mMessage, field, Templates::SetterTemplateDeclarationComplexType);
+            mPrinter->Print(propertyMap, Templates::SetterTemplateDeclarationComplexType);
             break;
         default:
-            printField(mMessage, field, Templates::SetterTemplate);
+            mPrinter->Print(propertyMap, Templates::SetterTemplate);
             break;
         }
     }
-
-    Outdent();
-
-    Indent();
-    mPrinter->Print({{"classname", mClassName}}, Templates::ManualRegistrationDeclaration);
     Outdent();
+}
 
-    mPrinter->Print(Templates::SignalsBlockTemplate);
-
+void ProtobufClassGenerator::printSignals()
+{
     Indent();
     for (int i = 0; i < mMessage->field_count(); i++) {
-        printField(mMessage, mMessage->field(i), Templates::SignalTemplate);
+        mPrinter->Print(common::producePropertyMap(mMessage->field(i), mMessage), Templates::SignalTemplate);
     }
     Outdent();
+}
 
-    printPrivate();
+
+void ProtobufClassGenerator::printPrivateMethods()
+{
     Indent();
     for (int i = 0; i < mMessage->field_count(); i++) {
         auto field = mMessage->field(i);
-        if (hasQmlAlias(field)) {
-            printField(mMessage, field, Templates::NonScriptableGetterTemplate);
-            printField(mMessage, field, Templates::NonScriptableSetterTemplate);
+        auto propertyMap = common::producePropertyMap(field, mMessage);
+        if (common::hasQmlAlias(field)) {
+            mPrinter->Print(propertyMap, Templates::NonScriptableGetterTemplate);
+            mPrinter->Print(propertyMap, Templates::NonScriptableSetterTemplate);
         }
     }
     Outdent();
 }
 
+void ProtobufClassGenerator::printClassBody()
+{
+    printProperties();
+    printQEnums(mMessage);
+
+    printPublicBlock();
+    printMaps();
+
+    Indent();
+    printConstructors();
+    printDestructor();
+
+    printCopyFunctionality();
+    printMoveSemantic();
+
+    printComparisonOperators();
+    Outdent();
+
+    printGetters();
+    printSetters();
+
+    Indent();
+    mPrinter->Print({{"classname", mClassName}}, Templates::ManualRegistrationDeclaration);
+    Outdent();
+
+    printSignalsBlock();
+    printSignals();
+
+    printPrivateBlock();
+    printPrivateMethods();
+
+    printPrivateBlock();
+    printClassMembers();
+}
+
 void ProtobufClassGenerator::printListType()
 {
     mPrinter->Print({{"classname", mClassName}}, Templates::ComplexListTypeUsingTemplate);
@@ -339,29 +326,18 @@ void ProtobufClassGenerator::printClassMembers()
     Indent();
     for (int i = 0; i < mMessage->field_count(); i++) {
         auto field = mMessage->field(i);
+        auto propertyMap = common::producePropertyMap(field, mMessage);
         if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
-            printField(mMessage, field, Templates::ComplexMemberTemplate);
+            mPrinter->Print(propertyMap, Templates::ComplexMemberTemplate);
+        } else if(field->is_repeated() && !field->is_map()){
+             mPrinter->Print(propertyMap, Templates::ListMemberTemplate);
         } else {
-            printField(mMessage, field, Templates::MemberTemplate);
+            mPrinter->Print(propertyMap, Templates::MemberTemplate);
         }
     }
     Outdent();
 }
 
-std::set<std::string> ProtobufClassGenerator::extractModels() const
-{
-    std::set<std::string> extractedModels;
-    for (int i = 0; i < mMessage->field_count(); i++) {
-        const FieldDescriptor *field = mMessage->field(i);
-        if (field->is_repeated()
-                && field->type() == FieldDescriptor::TYPE_MESSAGE) {
-            std::string typeName = field->message_type()->name();
-            extractedModels.insert(typeName);
-        }
-    }
-    return extractedModels;
-}
-
 void ProtobufClassGenerator::run()
 {
     printDisclaimer();
@@ -371,17 +347,11 @@ void ProtobufClassGenerator::run()
     printFieldClassDeclaration();
     printComments(mMessage);
     printClassDeclaration();
-    printProperties();
-    printPrivate();
-    printClassMembers();
-    printPublic();
-    printDestructor();
+    printClassBody();
     encloseClass();
     printListType();
     encloseNamespaces();
-    printMetaTypeDeclaration();
-    printMapsMetaTypesDeclaration();
-    printLocalEnumsMetaTypesDeclaration();
+    printMetaTypesDeclaration();
 }
 
 void ProtobufClassGenerator::printDestructor()

+ 12 - 10
src/generator/protobufclassgenerator.h

@@ -30,6 +30,7 @@
 #include <memory>
 
 #include "templates.h"
+#include "generatorcommon.h"
 
 namespace google { namespace protobuf {
 class FieldDescriptor;
@@ -41,8 +42,6 @@ class ZeroCopyOutputStream;
 namespace QtProtobuf {
 namespace generator {
 
-using PropertyMap = std::map<std::string, std::string>;
-
 /*!
  * \ingroup generator
  * \private
@@ -56,26 +55,29 @@ public:
     ProtobufClassGenerator(const ::google::protobuf::Descriptor *message, const std::shared_ptr<::google::protobuf::io::Printer> &printer);
     virtual ~ProtobufClassGenerator() = default;
 
-    void run() override;
+    void run();
 
     void printIncludes();
     void printCopyFunctionality();
     void printMoveSemantic();
     void printComparisonOperators();
+    void printClassBody();
     void printProperties();
+    void printGetters();
+    void printSetters();
+    void printSignals();
+    void printPrivateMethods();
     void printClassMembers();
-    void printConstructor();
+    void printConstructor(int fieldCount);
+    void printConstructors();
     void printDestructor();
     void printListType();
     void printMaps();
-    void printMapsMetaTypesDeclaration();
-    void printLocalEnumsMetaTypesDeclaration();
-    void printFieldClassDeclaration();
-
-    std::set<std::string> extractModels() const;
 
+    void printMetaTypesDeclaration();
+    void printFieldClassDeclaration();
 private:
-    static bool isListType(const ::google::protobuf::FieldDescriptor *field);
+    TypeMap mTypeMap;
 };
 
 }

+ 8 - 10
src/generator/protobufsourcegenerator.cpp

@@ -39,33 +39,31 @@ ProtobufSourceGenerator::ProtobufSourceGenerator(const google::protobuf::Descrip
                                                  const std::shared_ptr<google::protobuf::io::ZeroCopyOutputStream> &out) :
     ClassSourceGeneratorBase(message->full_name(), out)
   , mMessage(message)
+  , mTypeMap(common::produceMessageTypeMap(message, nullptr))
 {
 }
 
 ProtobufSourceGenerator::ProtobufSourceGenerator(const google::protobuf::Descriptor *message, const std::shared_ptr<::google::protobuf::io::Printer> &printer) :
     ClassSourceGeneratorBase(message->full_name(), printer)
   , mMessage(message)
+  , mTypeMap(common::produceMessageTypeMap(message, nullptr))
 {
 }
 
 void ProtobufSourceGenerator::printRegisterBody()
 {
-    const std::map<std::string, std::string> registrationProperties = {{"classname", mClassName},
-                                                                       {"namespaces", mNamespacesColonDelimited},
-                                                                       {"package", mMessage->file()->package()}
-                                                                      };
-    mPrinter->Print(registrationProperties,
+    mPrinter->Print(mTypeMap,
                     Templates::ManualRegistrationComplexTypeDefinition);
     Indent();
     if (GeneratorOptions::instance().hasQml()) {
-        mPrinter->Print(registrationProperties, Templates::RegisterQmlListPropertyMetaTypeTemplate);
-        mPrinter->Print(registrationProperties, Templates::QmlRegisterTypeTemplate);
+        mPrinter->Print(mTypeMap, Templates::RegisterQmlListPropertyMetaTypeTemplate);
+        mPrinter->Print(mTypeMap, Templates::QmlRegisterTypeTemplate);
     }
 
     for (int i = 0; i < mMessage->field_count(); i++) {
         const FieldDescriptor *field = mMessage->field(i);
         if (field->type() == FieldDescriptor::TYPE_ENUM
-                && isLocalMessageEnum(mMessage, field)) {
+                && common::isLocalEnum(field->enum_type(), mMessage)) {
             mPrinter->Print({{"type", mClassName + "::" + field->enum_type()->name() + Templates::ListSuffix},
                              {"namespaces", mNamespacesColonDelimited}},
                             Templates::RegisterMetaTypeTemplateNoNamespace);
@@ -395,15 +393,15 @@ void ProtobufSourceGenerator::printGetters()
 {
     for (int i = 0; i < mMessage->field_count(); i++) {
         const FieldDescriptor *field = mMessage->field(i);
+        auto propertyMap = common::producePropertyMap(field, mMessage);
         if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map() && !field->is_repeated()) {
             printField(mMessage, field, Templates::GetterPrivateMessageDefinitionTemplate);
             printField(mMessage, field, Templates::GetterMessageDefinitionTemplate);
         }
         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);
+                mPrinter->Print(propertyMap, Templates::GetterQmlListDefinitionTemplate);
             }
         }
     }

+ 3 - 0
src/generator/protobufsourcegenerator.h

@@ -27,6 +27,8 @@
 
 #include "classsourcegeneratorbase.h"
 
+#include "generatorcommon.h"
+
 namespace QtProtobuf {
 namespace generator {
 
@@ -38,6 +40,7 @@ namespace generator {
 class ProtobufSourceGenerator : public ClassSourceGeneratorBase
 {
     const google::protobuf::Descriptor *mMessage;
+    TypeMap mTypeMap;
 public:
     ProtobufSourceGenerator(const google::protobuf::Descriptor *message, const std::shared_ptr<google::protobuf::io::ZeroCopyOutputStream> &out);
     ProtobufSourceGenerator(const google::protobuf::Descriptor *message, const std::shared_ptr<::google::protobuf::io::Printer> &printer);

+ 1 - 1
src/generator/servergenerator.h

@@ -56,7 +56,7 @@ public:
         printIncludes();
         printNamespaces();
         printClassName();
-        printPublic();
+        printPublicBlock();
         printMethodsDeclaration(Templates::ServerMethodDeclarationTemplate);
         encloseClass();
         encloseNamespaces();

+ 4 - 11
src/generator/singlefilegenerator.cpp

@@ -129,10 +129,9 @@ bool SingleFileGenerator::GenerateMessages(const ::google::protobuf::FileDescrip
         enumSourceGen2.run();
     }
 
-    std::vector<std::string> namespaces;
+    std::vector<std::string> namespaces = utils::split(file->package(), '.');
     std::string namespacesColonDelimited;
 
-    utils::split(file->package(), namespaces, '.');
     assert(namespaces.size() > 0);
     for (size_t i = 0; i < namespaces.size(); i++) {
         if (i > 0) {
@@ -159,16 +158,10 @@ bool SingleFileGenerator::GenerateMessages(const ::google::protobuf::FileDescrip
         classGen.printNamespaces();
         classGen.printComments(message);
         classGen.printClassDeclaration();
-        classGen.printProperties();
-        classGen.printPrivate();
-        classGen.printClassMembers();
-        classGen.printPublic();
-        classGen.printDestructor();
+        classGen.printClassBody();
         classGen.encloseClass();
         classGen.encloseNamespaces();
-        classGen.printMetaTypeDeclaration();
-        classGen.printMapsMetaTypesDeclaration();
-        classGen.printLocalEnumsMetaTypesDeclaration();
+        classGen.printMetaTypesDeclaration();
 
         ProtobufSourceGenerator srcGen(message,
                                        outSourcePrinter);
@@ -263,7 +256,7 @@ bool SingleFileGenerator::GenerateServices(const ::google::protobuf::FileDescrip
                                   outHeaderPrinter);
         clientGen.printNamespaces();
         clientGen.printClientClass();
-        clientGen.printPublic();
+        clientGen.printPublicBlock();
         clientGen.printConstructor();
         clientGen.printClientMethodsDeclaration();
         clientGen.encloseClass();

+ 45 - 39
src/generator/templates.cpp

@@ -56,18 +56,16 @@ const char *Templates::GlobalEnumIncludeTemplate = "#include <globalenums.h>\n";
 
 const char *Templates::UsingQtProtobufNamespaceTemplate = "\nusing namespace QtProtobuf;\n";
 const char *Templates::ManualRegistrationDeclaration = "static void registerTypes();\n";
-const char *Templates::ManualRegistrationComplexTypeDefinition = "void $classname$::registerTypes()\n{\n"
-                                                                 "    qRegisterMetaType<$classname$>(\"$classname$\");\n"
-                                                                 "    qRegisterMetaType<$classname$Repeated>(\"$classname$Repeated\");\n"
-                                                                 "    qRegisterMetaType<$classname$>(\"$namespaces$::$classname$\");\n"
-                                                                 "    qRegisterMetaType<$classname$Repeated>(\"$namespaces$::$classname$Repeated\");\n"
+const char *Templates::ManualRegistrationComplexTypeDefinition = "void $type$::registerTypes()\n{\n"
+                                                                 "    qRegisterMetaType<$type$>(\"$full_type$\");\n"
+                                                                 "    qRegisterMetaType<$list_type$>(\"$full_list_type$\");\n"
                                                                  "";
 const char *Templates::ManualRegistrationGlobalEnumDefinition = "void $classname$::registerTypes()\n{\n"
                                                                  "";
 const char *Templates::ComplexGlobalEnumFieldRegistrationTemplate = "qRegisterMetaType<$classname$::$enum$>(\"$namespaces$::$classname$::$enum$\");\n";
 const char *Templates::ComplexListTypeUsingTemplate = "using $classname$Repeated = QList<QSharedPointer<$classname$>>;\n";
-const char *Templates::MapTypeUsingTemplate = "using $classname$ = QMap<$key$, $value$>;\n";
-const char *Templates::MessageMapTypeUsingTemplate = "using $classname$ = QMap<$key$, QSharedPointer<$value$>>;\n";
+const char *Templates::MapTypeUsingTemplate = "using $type$ = QMap<$key_type$, $value_type$>;\n";
+const char *Templates::MessageMapTypeUsingTemplate = "using $type$ = QMap<$key_type$, QSharedPointer<$value_type$>>;\n";
 
 const char *Templates::EnumTypeRepeatedTemplate = "using $enum$Repeated = QList<$enum$>;\n";
 
@@ -83,20 +81,28 @@ const char *Templates::ProtoClassDefinitionTemplate = "\nclass $classname$ : pub
                                                       "    Q_PROTOBUF_OBJECT\n"
                                                       "    Q_DECLARE_PROTOBUF_SERIALIZERS($classname$)\n";
 
-const char *Templates::PropertyTemplate = "Q_PROPERTY($type$ $property_name$ READ $property_name$ WRITE set$property_name_cap$ NOTIFY $property_name$Changed SCRIPTABLE $scriptable$)\n";
-const char *Templates::NonScriptablePropertyTemplate = "Q_PROPERTY($type$ $property_name$_p READ $property_name$ WRITE set$property_name_cap$ NOTIFY $property_name$Changed SCRIPTABLE false)\n";
+const char *Templates::PropertyTemplate = "Q_PROPERTY($property_type$ $property_name$ READ $property_name$ WRITE set$property_name_cap$ NOTIFY $property_name$Changed SCRIPTABLE $scriptable$)\n";
+const char *Templates::RepeatedPropertyTemplate = "Q_PROPERTY($property_list_type$ $property_name$ READ $property_name$ WRITE set$property_name_cap$ NOTIFY $property_name$Changed SCRIPTABLE $scriptable$)\n";
+const char *Templates::NonScriptablePropertyTemplate = "Q_PROPERTY($property_type$ $property_name$_p READ $property_name$ WRITE set$property_name_cap$ NOTIFY $property_name$Changed SCRIPTABLE false)\n";
 const char *Templates::NonScriptableAliasPropertyTemplate = "Q_PROPERTY($qml_alias_type$ $property_name$ READ $property_name$_p WRITE set$property_name_cap$_p NOTIFY $property_name$Changed SCRIPTABLE true)\n";
-const char *Templates::MessagePropertyTemplate = "Q_PROPERTY($type$ *$property_name$ READ $property_name$_p WRITE set$property_name_cap$_p NOTIFY $property_name$Changed)\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 = "std::unique_ptr<$type$> m_$property_name$;\n";
-const char *Templates::EnumMemberTemplate = "::$type$ m_$property_name$;\n";
+const char *Templates::MessagePropertyTemplate = "Q_PROPERTY($property_type$ *$property_name$ READ $property_name$_p WRITE set$property_name_cap$_p NOTIFY $property_name$Changed)\n";
+const char *Templates::QmlListPropertyTemplate = "Q_PROPERTY(QQmlListProperty<$property_type$> $property_name$Data READ $property_name$_l NOTIFY $property_name$Changed)\n";
+
+const char *Templates::ConstructorParameterTemplate = "$scope_type$ $property_name$,";
+const char *Templates::ConstructorMessageParameterTemplate = "const $scope_type$ &$property_name$,";
+const char *Templates::ConstructorRepeatedParameterTemplate = "const $scope_list_type$ &$property_name$,";
+const char *Templates::ProtoConstructorBeginTemplate = "$classname$(";
+const char *Templates::ProtoConstructorEndTemplate = "QObject *parent = nullptr);\n";
+
+const char *Templates::MemberTemplate = "$scope_type$ m_$property_name$;\n";
+const char *Templates::ListMemberTemplate = "$scope_list_type$ m_$property_name$;\n";
+const char *Templates::ComplexMemberTemplate = "std::unique_ptr<$scope_type$> m_$property_name$;\n";
 const char *Templates::PublicBlockTemplate = "\npublic:\n";
 const char *Templates::PrivateBlockTemplate = "\nprivate:\n";
 const char *Templates::EnumDefinitionTemplate = "enum $enum$ {\n";
 const char *Templates::EnumFieldTemplate = "$enumvalue$ = $value$,\n";
-const char *Templates::ProtoConstructorTemplate = "$classname$($parameter_list$QObject *parent = nullptr);\n";
+
+
 const char *Templates::ProtoConstructorDefinitionTemplate = "$classname$::$classname$($parameter_list$QObject *parent) : QObject(parent)";
 const char *Templates::ConstructorTemplate = "$classname$();\n";
 const char *Templates::QObjectConstructorTemplate = "explicit $classname$(QObject *parent = nullptr);\n";
@@ -151,12 +157,12 @@ const char *Templates::NotEqualOperatorDefinitionTemplate = "bool $classname$::o
                                                   "    return !this->operator ==(other);\n"
                                                   "}\n\n";
 
-const char *Templates::GetterPrivateMessageDeclarationTemplate = "$type$ *$property_name$_p() const;\n";
+const char *Templates::GetterPrivateMessageDeclarationTemplate = "$getter_type$ *$property_name$_p() const;\n";
 const char *Templates::GetterPrivateMessageDefinitionTemplate = "$type$ *$classname$::$property_name$_p() const\n{\n"
                                         "    return m_$property_name$.get();\n"
                                         "}\n\n";
 
-const char *Templates::GetterMessageDeclarationTemplate = "const $type$ &$property_name$() const;\n";
+const char *Templates::GetterMessageDeclarationTemplate = "const $getter_type$ &$property_name$() const;\n";
 const char *Templates::GetterMessageDefinitionTemplate = "const $type$ &$classname$::$property_name$() const\n{\n"
                                         "    return *m_$property_name$;\n"
                                         "}\n\n";
@@ -169,17 +175,16 @@ const char *Templates::NonScriptableGetterTemplate = "$qml_alias_type$ $property
                                         "    return m_$property_name$;\n"
                                         "}\n\n";
 
-const char *Templates::GetterContainerExtraDeclarationTemplate = "$type$ &$property_name$();\n";
-const char *Templates::GetterContainerExtraDefinitionTemplate = "$type$ &$classname$::$property_name$()\n{\n"
+const char *Templates::GetterContainerExtraTemplate = "$getter_type$ &$property_name$() {\n"
                                         "    return m_$property_name$;\n"
                                         "}\n\n";
 
-const char *Templates::GetterQmlListDeclarationTemplate = "QQmlListProperty<$type_nolist$> $property_name$_l();\n";
-const char *Templates::GetterQmlListDefinitionTemplate = "QQmlListProperty<$type_nolist$> $classname$::$property_name$_l()\n{\n"
-                                               "    return QtProtobuf::constructQmlListProperty<$type_nolist$>(this, &m_$property_name$);\n"
+const char *Templates::GetterQmlListDeclarationTemplate = "QQmlListProperty<$scope_type$> $property_name$_l();\n";
+const char *Templates::GetterQmlListDefinitionTemplate = "QQmlListProperty<$full_type$> $classname$::$property_name$_l()\n{\n"
+                                               "    return QtProtobuf::constructQmlListProperty<$scope_type$>(this, &m_$property_name$);\n"
                                                "}\n\n";
 
-const char *Templates::SetterPrivateTemplateDeclarationMessageType = "void set$property_name_cap$_p($type$ *$property_name$);\n";
+const char *Templates::SetterPrivateTemplateDeclarationMessageType = "void set$property_name_cap$_p($setter_type$ *$property_name$);\n";
 const char *Templates::SetterPrivateTemplateDefinitionMessageType = "void $classname$::set$property_name_cap$_p($type$ *$property_name$)\n{\n"
                                                    "    if ($property_name$ == nullptr) {\n"
                                                    "        *m_$property_name$ = {};\n"
@@ -193,7 +198,7 @@ const char *Templates::SetterPrivateTemplateDefinitionMessageType = "void $class
                                                    "    delete $property_name$;\n"
                                                    "}\n\n";
 
-const char *Templates::SetterTemplateDeclarationMessageType = "void set$property_name_cap$(const $type$ &$property_name$);\n";
+const char *Templates::SetterTemplateDeclarationMessageType = "void set$property_name_cap$(const $setter_type$ &$property_name$);\n";
 const char *Templates::SetterTemplateDefinitionMessageType = "void $classname$::set$property_name_cap$(const $type$ &$property_name$)\n{\n"
                                                    "    if (*m_$property_name$ != $property_name$) {\n"
                                                    "        *m_$property_name$ = $property_name$;\n"
@@ -201,7 +206,7 @@ const char *Templates::SetterTemplateDefinitionMessageType = "void $classname$::
                                                    "    }\n"
                                                    "}\n\n";
 
-const char *Templates::SetterTemplateDeclarationComplexType = "void set$property_name_cap$(const $type$ &$property_name$);\n";
+const char *Templates::SetterTemplateDeclarationComplexType = "void set$property_name_cap$(const $setter_type$ &$property_name$);\n";
 const char *Templates::SetterTemplateDefinitionComplexType = "void $classname$::set$property_name_cap$(const $type$ &$property_name$)\n{\n"
                                                    "    if (m_$property_name$ != $property_name$) {\n"
                                                    "        m_$property_name$ = $property_name$;\n"
@@ -209,7 +214,7 @@ const char *Templates::SetterTemplateDefinitionComplexType = "void $classname$::
                                                    "    }\n"
                                                    "}\n\n";
 
-const char *Templates::SetterTemplate = "void set$property_name_cap$(const $type$ &$property_name$) {\n"
+const char *Templates::SetterTemplate = "void set$property_name_cap$(const $setter_type$ &$property_name$) {\n"
                                                    "    if (m_$property_name$ != $property_name$) {\n"
                                                    "        m_$property_name$ = $property_name$;\n"
                                                    "        $property_name$Changed();\n"
@@ -240,24 +245,23 @@ const char *Templates::MessagePropertyInitializerTemplate = "\n    , m_$property
 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";
-const char *Templates::DeclareMetaTypeListTemplate = "Q_DECLARE_METATYPE($namespaces$::$classname$Repeated)\n";
-const char *Templates::DeclareMessageMetaTypeTemplate = "Q_DECLARE_METATYPE($namespaces$::$classname$)\n"
-                                                        "Q_DECLARE_OPAQUE_POINTER($namespaces$::$classname$)\n";
+const char *Templates::DeclareMetaTypeTemplate = "Q_DECLARE_METATYPE($full_type$)\n";
+const char *Templates::DeclareMetaTypeListTemplate = "Q_DECLARE_METATYPE($full_list_type$)\n";
+const char *Templates::DeclareMessageMetaTypeTemplate = "Q_DECLARE_METATYPE($full_type$)\n"
+                                                        "Q_DECLARE_OPAQUE_POINTER($full_type$)\n";
 
-const char *Templates::DeclareComplexListTypeTemplate = "Q_DECLARE_METATYPE($namespaces$::$classname$Repeated)\n";
-const char *Templates::DeclareComplexQmlListTypeTemplate = "Q_DECLARE_METATYPE(QQmlListProperty<$namespaces$::$classname$>)\n";
+const char *Templates::DeclareComplexListTypeTemplate = "Q_DECLARE_METATYPE($full_list_type$)\n";
+const char *Templates::DeclareComplexQmlListTypeTemplate = "Q_DECLARE_METATYPE(QQmlListProperty<$full_type$>)\n";
 
-const char *Templates::DeclareMetaTypeMapTemplate = "#ifndef Q_PROTOBUF_MAP_$key$_$value$\n"
-                                                    "#define Q_PROTOBUF_MAP_$key$_$value$\n"
-                                                    "Q_DECLARE_METATYPE($namespaces$::$classname$)\n"
+const char *Templates::DeclareMetaTypeMapTemplate = "#ifndef Q_PROTOBUF_MAP_$key_type_underscore$_$value_type_underscore$\n"
+                                                    "#define Q_PROTOBUF_MAP_$key_type_underscore$_$value_type_underscore$\n"
+                                                    "Q_DECLARE_METATYPE($full_type$)\n"
                                                     "#endif\n";
 
 const char *Templates::RegisterMetaTypeDefaultTemplate = "qRegisterMetaType<$namespaces$::$type$>();\n";
 const char *Templates::RegisterMetaTypeTemplateNoNamespace = "qRegisterMetaType<$namespaces$::$type$>(\"$type$\");\n";
 const char *Templates::RegisterMetaTypeTemplate = "qRegisterMetaType<$namespaces$::$type$>(\"$namespaces$::$type$\");\n";
-const char *Templates::RegisterQmlListPropertyMetaTypeTemplate = "qRegisterMetaType<QQmlListProperty<$namespaces$::$classname$>>(\"QQmlListProperty<$namespaces$::$classname$>\");\n"
-                                                                 "qRegisterMetaType<QQmlListProperty<$namespaces$::$classname$>>(\"QQmlListProperty<$classname$>\");\n";
+const char *Templates::RegisterQmlListPropertyMetaTypeTemplate = "qRegisterMetaType<QQmlListProperty<$full_type$>>(\"QQmlListProperty<$full_type$>\");\n";
 
 
 const char *Templates::QEnumTemplate = "Q_ENUM($type$)\n";
@@ -296,7 +300,7 @@ const char *Templates::RegisterSerializersTemplate = "qRegisterProtobufType<$cla
 const char *Templates::RegisterEnumSerializersTemplate = "qRegisterProtobufEnumType<$type$>();\n";
 const char *Templates::RegistrarTemplate = "static QtProtobuf::ProtoTypeRegistrar<$classname$> ProtoTypeRegistrar$classname$(qRegisterProtobufType<$classname$>);\n";
 const char *Templates::EnumRegistrarTemplate = "static QtProtobuf::ProtoTypeRegistrar<$classname$> ProtoTypeRegistrar$classname$($classname$::registerTypes);\n";
-const char *Templates::QmlRegisterTypeTemplate = "qmlRegisterType<$namespaces$::$classname$>(\"$package$\", 1, 0, \"$classname$\");\n";
+const char *Templates::QmlRegisterTypeTemplate = "qmlRegisterType<$full_type$>(\"$qml_package$\", 1, 0, \"$type$\");\n";
 const char *Templates::QmlRegisterTypeUncreatableTemplate = "qmlRegisterUncreatableType<$namespaces$::$classname$>(\"$package$\", 1, 0, \"$classname$\", \"$namespaces$::$classname$ Could not be created from qml context\");\n";
 
 
@@ -337,3 +341,5 @@ const char *Templates::ProtoFileSuffix = ".qpb";
 const char *Templates::GrpcFileSuffix = "_grpc";
 
 const char *Templates::EnumClassSuffix = "Gadget";
+
+const char *Templates::QtProtobufNamespace = "QtProtobuf";

+ 18 - 5
src/generator/templates.h

@@ -66,20 +66,32 @@ public:
     static const char *ConstructorHeaderTemplate;
     static const char *ClassDefinitionTemplate;
     static const char *QObjectMacro;
+
     static const char *PropertyTemplate;
+    static const char *RepeatedPropertyTemplate;
     static const char *NonScriptablePropertyTemplate;
     static const char *NonScriptableAliasPropertyTemplate;
     static const char *MessagePropertyTemplate;
     static const char *QmlListPropertyTemplate;
+
+    static const char *ConstructorParameterTemplate;
+    static const char *ConstructorMessageParameterTemplate;
+    static const char *ConstructorRepeatedParameterTemplate;
+    static const char *ProtoConstructorBeginTemplate;
+    static const char *ProtoConstructorEndTemplate;
+
+    static const char *ConstructorParameterDefinitionTemplate;
+    static const char *ConstructorMessageParameterDefinitionTemplate;
+    static const char *ConstructorRepeatedParameterDefinitionTemplate;
+    static const char *ProtoConstructorDefinitionTemplate;
+
     static const char *MemberTemplate;
+    static const char *ListMemberTemplate;
     static const char *ComplexMemberTemplate;
-    static const char *EnumMemberTemplate;
     static const char *PublicBlockTemplate;
     static const char *PrivateBlockTemplate;
     static const char *EnumDefinitionTemplate;
     static const char *EnumFieldTemplate;
-    static const char *ProtoConstructorTemplate;
-    static const char *ProtoConstructorDefinitionTemplate;
     static const char *ConstructorTemplate;
     static const char *QObjectConstructorTemplate;
     static const char *CopyConstructorDeclarationTemplate;
@@ -117,8 +129,7 @@ public:
     static const char *GetterMessageDefinitionTemplate;
     static const char *GetterTemplate;
     static const char *NonScriptableGetterTemplate;
-    static const char *GetterContainerExtraDeclarationTemplate;
-    static const char *GetterContainerExtraDefinitionTemplate;
+    static const char *GetterContainerExtraTemplate;
     static const char *GetterQmlListDeclarationTemplate;
     static const char *GetterQmlListDefinitionTemplate;
 
@@ -186,6 +197,8 @@ public:
     static const char *EnumClassSuffix;
 
     static const std::unordered_map<::google::protobuf::FieldDescriptor::Type, std::string> TypeReflection;
+
+    static const char *QtProtobufNamespace;
 };
 
 } //namespace generator

+ 5 - 3
src/generator/utils.h

@@ -52,17 +52,19 @@ namespace generator {
  */
 class utils {
 public:
-static void split(const std::string &str, std::vector<std::string> &container, char delim)
+static std::vector<std::string> split(const std::string &str, char delim)
 {
-    container.clear();
+    std::vector<std::string> container;
     if (str.size() <= 0) {
-        return;
+        return container;
     }
     std::stringstream stream(str);
     std::string token;
     while (std::getline(stream, token, delim)) {
         container.push_back(token);
     }
+
+    return container;
 }
 
 static void replace(std::string &data, const std::string &from, const std::string &to) {

+ 8 - 8
tests/test_protobuf/duplicatedmetatypestest.cpp

@@ -52,14 +52,14 @@ void DuplicatedMetatypesTest::SetUp()
 
 
 TEST_F(DuplicatedMetatypesTest, SimpleTest) {
-    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message1, qtprotobufnamespace::duplicated_metatypes::Message1::OptsEntry>(1, "Message1::OptsEntry", "opts");
-    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message2, qtprotobufnamespace::duplicated_metatypes::Message2::OptsEntry>(1, "Message2::OptsEntry", "opts");
-    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message3, qtprotobufnamespace::duplicated_metatypes::Message3::OptsEntry>(1, "Message3::OptsEntry", "opts");
-    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message4, qtprotobufnamespace::duplicated_metatypes::Message4::OptsEntry>(1, "Message4::OptsEntry", "opts");
-    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message5, qtprotobufnamespace::duplicated_metatypes::Message5::OptsEntry>(1, "Message5::OptsEntry", "opts");
-    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message6, qtprotobufnamespace::duplicated_metatypes::Message6::OptsEntry>(1, "Message6::OptsEntry", "opts");
-    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message7, qtprotobufnamespace::duplicated_metatypes::Message7::OptsEntry>(1, "Message7::OptsEntry", "opts");
-    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message8, qtprotobufnamespace::duplicated_metatypes::Message8::OptsEntry>(1, "Message8::OptsEntry", "opts");
+    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message1, qtprotobufnamespace::duplicated_metatypes::Message1::OptsEntry>(1, "qtprotobufnamespace::duplicated_metatypes::Message1::OptsEntry", "opts");
+    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message2, qtprotobufnamespace::duplicated_metatypes::Message2::OptsEntry>(1, "qtprotobufnamespace::duplicated_metatypes::Message2::OptsEntry", "opts");
+    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message3, qtprotobufnamespace::duplicated_metatypes::Message3::OptsEntry>(1, "qtprotobufnamespace::duplicated_metatypes::Message3::OptsEntry", "opts");
+    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message4, qtprotobufnamespace::duplicated_metatypes::Message4::OptsEntry>(1, "qtprotobufnamespace::duplicated_metatypes::Message4::OptsEntry", "opts");
+    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message5, qtprotobufnamespace::duplicated_metatypes::Message5::OptsEntry>(1, "qtprotobufnamespace::duplicated_metatypes::Message5::OptsEntry", "opts");
+    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message6, qtprotobufnamespace::duplicated_metatypes::Message6::OptsEntry>(1, "qtprotobufnamespace::duplicated_metatypes::Message6::OptsEntry", "opts");
+    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message7, qtprotobufnamespace::duplicated_metatypes::Message7::OptsEntry>(1, "qtprotobufnamespace::duplicated_metatypes::Message7::OptsEntry", "opts");
+    assertMessagePropertyRegistered<qtprotobufnamespace::duplicated_metatypes::Message8, qtprotobufnamespace::duplicated_metatypes::Message8::OptsEntry>(1, "qtprotobufnamespace::duplicated_metatypes::Message8::OptsEntry", "opts");
 }
 
 }

+ 8 - 8
tests/test_protobuf/simpletest.cpp.inc

@@ -240,7 +240,7 @@ TEST_F(SimpleTest, SimpleLocalEnumListTest)
     ASSERT_GT(SimpleEnumListMessage::staticMetaObject.enumeratorCount(), 0);
 
     const char *propertyName = "localEnumList";
-    assertMessagePropertyRegistered<SimpleEnumListMessage, SimpleEnumListMessage::LocalEnumRepeated>(1,  "SimpleEnumListMessage::LocalEnumRepeated", propertyName);
+    assertMessagePropertyRegistered<SimpleEnumListMessage, SimpleEnumListMessage::LocalEnumRepeated>(1,  "qtprotobufnamespace::tests::SimpleEnumListMessage::LocalEnumRepeated", propertyName);
 
     SimpleEnumListMessage::LocalEnumRepeated value({SimpleEnumListMessage::LOCAL_ENUM_VALUE2,
                                                 SimpleEnumListMessage::LOCAL_ENUM_VALUE2,
@@ -642,7 +642,7 @@ TEST_F(SimpleTest, StepChildEnumListMessageTest)
 TEST_F(SimpleTest, SimpleSInt32StringMapMessageTest)
 {
     const char *propertyName = "mapField";
-    assertMessagePropertyRegistered<SimpleSInt32StringMapMessage, SimpleSInt32StringMapMessage::MapFieldEntry>(1, "SimpleSInt32StringMapMessage::MapFieldEntry", propertyName);
+    assertMessagePropertyRegistered<SimpleSInt32StringMapMessage, SimpleSInt32StringMapMessage::MapFieldEntry>(1, "qtprotobufnamespace::tests::SimpleSInt32StringMapMessage::MapFieldEntry", propertyName);
 
     ASSERT_TRUE(QMetaType::isRegistered(qMetaTypeId<SimpleSInt32StringMapMessage::MapFieldEntry>()));
 
@@ -665,7 +665,7 @@ TEST_F(SimpleTest, SimpleSInt32StringMapMessageTest)
 TEST_F(SimpleTest, SimpleStringStringMapMessageTest)
 {
     const char *propertyName = "mapField";
-    assertMessagePropertyRegistered<SimpleStringStringMapMessage, SimpleStringStringMapMessage::MapFieldEntry>(13, "SimpleStringStringMapMessage::MapFieldEntry", propertyName);
+    assertMessagePropertyRegistered<SimpleStringStringMapMessage, SimpleStringStringMapMessage::MapFieldEntry>(13, "qtprotobufnamespace::tests::SimpleStringStringMapMessage::MapFieldEntry", propertyName);
 
     ASSERT_TRUE(QMetaType::isRegistered(qMetaTypeId<SimpleStringStringMapMessage::MapFieldEntry>()));
 
@@ -775,14 +775,14 @@ TEST_F(SimpleTest, UnderscoresTest)
 
 TEST_F(SimpleTest, SequenceTest)
 {
-    assertMessagePropertyRegistered<sequence::TestMessageSequence, sequence::TestMessageSequence2*>(1, "TestMessageSequence2*", "testField");
+    assertMessagePropertyRegistered<sequence::TestMessageSequence, sequence::TestMessageSequence2*>(1, "qtprotobufnamespace::tests::sequence::TestMessageSequence2*", "testField");
     assertMessagePropertyRegistered<sequence::TestMessageSequence2, bool>(1, "bool", "testField");
 }
 
 TEST_F(SimpleTest, CyclingTest)
 {
-    assertMessagePropertyRegistered<sequence::CyclingFirstDependency, sequence::CyclingSecondDependency*>(1, "CyclingSecondDependency*", "testField");
-    assertMessagePropertyRegistered<sequence::CyclingSecondDependency, sequence::CyclingFirstDependency*>(1, "CyclingFirstDependency*", "testField");
+    assertMessagePropertyRegistered<sequence::CyclingFirstDependency, sequence::CyclingSecondDependency*>(1, "qtprotobufnamespace::tests::sequence::CyclingSecondDependency*", "testField");
+    assertMessagePropertyRegistered<sequence::CyclingSecondDependency, sequence::CyclingFirstDependency*>(1, "qtprotobufnamespace::tests::sequence::CyclingFirstDependency*", "testField");
 }
 
 TEST_F(SimpleTest, UpperCaseTest)
@@ -844,8 +844,8 @@ TEST_F(SimpleTest, LowerCaseEnumTest)
 
 TEST_F(SimpleTest, MapRepeatedFieldSequenceTest)
 {
-    assertMessagePropertyRegistered<sequence::RepeatedFieldSequence, sequence::RepeatedFieldSequence2Repeated>(1, "RepeatedFieldSequence2Repeated", "testField");
-    assertMessagePropertyRegistered<sequence::MapFieldSequence, sequence::MapFieldSequence::TestFieldEntry>(1, "MapFieldSequence::TestFieldEntry", "testField");
+    assertMessagePropertyRegistered<sequence::RepeatedFieldSequence, sequence::RepeatedFieldSequence2Repeated>(1, "qtprotobufnamespace::tests::sequence::RepeatedFieldSequence2Repeated", "testField");
+    assertMessagePropertyRegistered<sequence::MapFieldSequence, sequence::MapFieldSequence::TestFieldEntry>(1, "qtprotobufnamespace::tests::sequence::MapFieldSequence::TestFieldEntry", "testField");
 }
 
 } // tests

+ 18 - 18
tests/test_wellknowntypes/simpletest.cpp

@@ -78,11 +78,11 @@ TEST_F(WellknowntypesTest, ApiTest)
     ASSERT_GT(qMetaTypeId<Api>(), 0);
 
     assertMessagePropertyRegistered<Api, QString>(1, "QString", "name");
-    assertMessagePropertyRegistered<Api, MethodRepeated>(2, "MethodRepeated", "methods");
-    assertMessagePropertyRegistered<Api, OptionRepeated>(3, "OptionRepeated", "options");
+    assertMessagePropertyRegistered<Api, MethodRepeated>(2, "google::protobuf::MethodRepeated", "methods");
+    assertMessagePropertyRegistered<Api, OptionRepeated>(3, "google::protobuf::OptionRepeated", "options");
     assertMessagePropertyRegistered<Api, QString>(4, "QString", "version");
-    assertMessagePropertyRegistered<Api, SourceContext>(5, "SourceContext*", "sourceContext", true);
-    assertMessagePropertyRegistered<Api, MixinRepeated>(6, "MixinRepeated", "mixins");
+    assertMessagePropertyRegistered<Api, SourceContext>(5, "google::protobuf::SourceContext*", "sourceContext", true);
+    assertMessagePropertyRegistered<Api, MixinRepeated>(6, "google::protobuf::MixinRepeated", "mixins");
     assertMessagePropertyRegistered<Api, SyntaxGadget::Syntax>(7, "google::protobuf::SyntaxGadget::Syntax", "syntax");
 }
 
@@ -94,7 +94,7 @@ TEST_F(WellknowntypesTest, MethodTest)
     assertMessagePropertyRegistered<Method, bool>(3, "bool", "requestStreaming");
     assertMessagePropertyRegistered<Method, QString>(4, "QString", "responseTypeUrl");
     assertMessagePropertyRegistered<Method, bool>(5, "bool", "responseStreaming");
-    assertMessagePropertyRegistered<Method, OptionRepeated>(6, "OptionRepeated", "options");
+    assertMessagePropertyRegistered<Method, OptionRepeated>(6, "google::protobuf::OptionRepeated", "options");
     assertMessagePropertyRegistered<Method, SyntaxGadget::Syntax>(7, "google::protobuf::SyntaxGadget::Syntax", "syntax");
 }
 
@@ -132,7 +132,7 @@ TEST_F(WellknowntypesTest, SourceContextTest)
 TEST_F(WellknowntypesTest, StructTest)
 {
     ASSERT_GT(qMetaTypeId<Struct>(), 0);
-    assertMessagePropertyRegistered<Struct, Struct::FieldsEntry>(1, "Struct::FieldsEntry", "fields");
+    assertMessagePropertyRegistered<Struct, Struct::FieldsEntry>(1, "google::protobuf::Struct::FieldsEntry", "fields");
 }
 
 TEST_F(WellknowntypesTest, ValueTest)
@@ -142,14 +142,14 @@ TEST_F(WellknowntypesTest, ValueTest)
     assertMessagePropertyRegistered<Value, double>(2, "double", "numberValue");
     assertMessagePropertyRegistered<Value, QString>(3, "QString", "stringValue");
     assertMessagePropertyRegistered<Value, bool>(4, "bool", "boolValue");
-    assertMessagePropertyRegistered<Value, Struct *>(5, "Struct*", "structValue");
-    assertMessagePropertyRegistered<Value, ListValue *>(6, "ListValue*", "listValue");
+    assertMessagePropertyRegistered<Value, Struct *>(5, "google::protobuf::Struct*", "structValue");
+    assertMessagePropertyRegistered<Value, ListValue *>(6, "google::protobuf::ListValue*", "listValue");
 }
 
 TEST_F(WellknowntypesTest, ListValueTest)
 {
     ASSERT_GT(qMetaTypeId<ListValue>(), 0);
-    assertMessagePropertyRegistered<ListValue, ValueRepeated>(1, "ValueRepeated", "values");
+    assertMessagePropertyRegistered<ListValue, ValueRepeated>(1, "google::protobuf::ValueRepeated", "values");
 }
 
 TEST_F(WellknowntypesTest, TimestampTest)
@@ -165,10 +165,10 @@ TEST_F(WellknowntypesTest, TypeTest)
     Q_PROPERTY(QStringList oneofs READ oneofs WRITE setOneofs NOTIFY oneofsChanged)
 
     assertMessagePropertyRegistered<Type, QString>(1, "QString", "name");
-    assertMessagePropertyRegistered<Type, FieldRepeated>(2, "FieldRepeated", "fields");
+    assertMessagePropertyRegistered<Type, FieldRepeated>(2, "google::protobuf::FieldRepeated", "fields");
     assertMessagePropertyRegistered<Type, QStringList>(3, "QStringList", "oneofs");
-    assertMessagePropertyRegistered<Type, OptionRepeated>(4, "OptionRepeated", "options");
-    assertMessagePropertyRegistered<Type, SourceContext *>(5, "SourceContext*", "sourceContext", true);
+    assertMessagePropertyRegistered<Type, OptionRepeated>(4, "google::protobuf::OptionRepeated", "options");
+    assertMessagePropertyRegistered<Type, SourceContext *>(5, "google::protobuf::SourceContext*", "sourceContext", true);
     assertMessagePropertyRegistered<Type, SyntaxGadget::Syntax>(6, "google::protobuf::SyntaxGadget::Syntax", "syntax");
 }
 
@@ -183,7 +183,7 @@ TEST_F(WellknowntypesTest, FieldTest)
     assertMessagePropertyRegistered<Field, QString>(6, "QString", "typeUrl");
     assertMessagePropertyRegistered<Field, QtProtobuf::int32>(7, "QtProtobuf::int32", "oneofIndex_p");
     assertMessagePropertyRegistered<Field, bool>(8, "bool", "packed");
-    assertMessagePropertyRegistered<Field, OptionRepeated>(9, "OptionRepeated", "options");
+    assertMessagePropertyRegistered<Field, OptionRepeated>(9, "google::protobuf::OptionRepeated", "options");
     assertMessagePropertyRegistered<Field, QString>(10, "QString", "jsonName");
     assertMessagePropertyRegistered<Field, QString>(11, "QString", "defaultValue");
 }
@@ -192,9 +192,9 @@ TEST_F(WellknowntypesTest, EnumTest)
 {
     ASSERT_GT(qMetaTypeId<Enum>(), 0);
     assertMessagePropertyRegistered<Enum, QString>(1, "QString", "name");
-    assertMessagePropertyRegistered<Enum, EnumValueRepeated>(2, "EnumValueRepeated", "enumvalue");
-    assertMessagePropertyRegistered<Enum, OptionRepeated>(3, "OptionRepeated", "options");
-    assertMessagePropertyRegistered<Enum, SourceContext *>(4, "SourceContext*", "sourceContext", true);
+    assertMessagePropertyRegistered<Enum, EnumValueRepeated>(2, "google::protobuf::EnumValueRepeated", "enumvalue");
+    assertMessagePropertyRegistered<Enum, OptionRepeated>(3, "google::protobuf::OptionRepeated", "options");
+    assertMessagePropertyRegistered<Enum, SourceContext *>(4, "google::protobuf::SourceContext*", "sourceContext", true);
     assertMessagePropertyRegistered<Enum, SyntaxGadget::Syntax>(5, "google::protobuf::SyntaxGadget::Syntax", "syntax");
 }
 
@@ -203,14 +203,14 @@ TEST_F(WellknowntypesTest, EnumValueTest)
     ASSERT_GT(qMetaTypeId<EnumValue>(), 0);
     assertMessagePropertyRegistered<EnumValue, QString>(1, "QString", "name");
     assertMessagePropertyRegistered<EnumValue, QtProtobuf::int32>(2, "QtProtobuf::int32", "number_p");
-    assertMessagePropertyRegistered<EnumValue, OptionRepeated>(3, "OptionRepeated", "options");
+    assertMessagePropertyRegistered<EnumValue, OptionRepeated>(3, "google::protobuf::OptionRepeated", "options");
 }
 
 TEST_F(WellknowntypesTest, OptionTest)
 {
     ASSERT_GT(qMetaTypeId<Option>(), 0);
     assertMessagePropertyRegistered<Option, QString>(1, "QString", "name");
-    assertMessagePropertyRegistered<Option, Any *>(2, "Any*", "value", true);
+    assertMessagePropertyRegistered<Option, Any *>(2, "google::protobuf::Any*", "value", true);
 }
 
 TEST_F(WellknowntypesTest, DoubleValueTest)