Преглед изворни кода

Complete maps generator

- Fix issue with unregistred metatype
- Minor improvements
- Update tests
- Implement support of initialization list for protobuf types
Alexey Edelev пре 6 година
родитељ
комит
d3f8b0c489

+ 2 - 2
examples/addressbook/proto/addressbook.proto

@@ -36,8 +36,8 @@ message Address {
     uint64 zipCode = 1;
     string streetAddress1 = 2;
     string streetAddress2 = 3;
-    string State = 4;
-    uint32 Country = 5;
+    string state = 4;
+    uint32 country = 5;
 }
 
 message Job {

+ 30 - 3
src/generator/protobufclassgenerator.cpp

@@ -269,8 +269,8 @@ std::string ProtobufClassGenerator::getTypeName(const FieldDescriptor *field)
         namespaceTypeName = getNamespacesList(msg, typeNamespace);
         typeName = namespaceTypeName.append(msg->name());
 
-        if ( field->is_map() ) {
-            return field->message_type()->name();
+        if (field->is_map()) {
+            return mClassName + "::" + field->message_type()->name();
         }
         if (field->is_repeated()) {
             return namespaceTypeName.append("List");
@@ -360,7 +360,33 @@ bool ProtobufClassGenerator::isComplexType(const FieldDescriptor *field)
 
 void ProtobufClassGenerator::printConstructor()
 {
-    mPrinter.Print({{"classname", mClassName}}, Templates::ProtoConstructorTemplate);
+    std::string parameterList;
+    for (int i = 0; i < mMessage->field_count(); i++) {
+        const FieldDescriptor* field = mMessage->field(i);
+        std::string fieldTypeName = getTypeName(field);
+        std::string fieldName = field->name();
+        fieldName[0] = ::tolower(fieldName[0]);
+        switch (field->type()) {
+        case FieldDescriptor::TYPE_BYTES:
+        case FieldDescriptor::TYPE_STRING:
+        case FieldDescriptor::TYPE_MESSAGE:
+            parameterList += "const " + fieldTypeName + " &" + fieldName + " = " + fieldTypeName + "()";
+            break;
+        default:
+            parameterList += fieldTypeName + " " + fieldName + " = " + "{}";
+            break;
+        }
+        parameterList += ", ";
+    }
+    mPrinter.Print({{"classname", mClassName},
+                    {"parameter_list", parameterList}}, Templates::ProtoConstructorTemplate);
+
+    for (int i = 0; i < mMessage->field_count(); i++) {
+        const FieldDescriptor* field = mMessage->field(i);
+        std::string fieldName = field->name();
+        fieldName[0] = ::tolower(fieldName[0]);
+        mPrinter.Print({{"property_name", fieldName}}, Templates::PropertyInitializerTemplate);
+    }
     mPrinter.Print(Templates::ConstructorContentTemplate);
 }
 
@@ -369,6 +395,7 @@ void ProtobufClassGenerator::printMaps()
     Indent();
     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));
             std::string valueType = getTypeName(field->message_type()->field(1));

+ 3 - 0
src/generator/protobufsourcegenerator.cpp

@@ -49,6 +49,9 @@ void ProtobufSourceGenerator::printRegisterBody()
     for (int i = 0; i < mMessage->field_count(); i++) {
         const FieldDescriptor* field = mMessage->field(i);
         if (field->is_map()) {
+            mPrinter.Print({{"classname", field->message_type()->name()},
+                            {"namespaces", mClassName}},
+                           Templates::RegisterMetaTypeTemplate);
             mPrinter.Print({{"classname", field->message_type()->name()},
                             {"namespaces", mNamespacesColonDelimited + "::" + mClassName}},
                            Templates::RegisterMetaTypeTemplate);

+ 4 - 2
src/generator/templates.cpp

@@ -74,7 +74,7 @@ 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$(QObject *parent = nullptr) : ProtobufObject(parent)\n";
+const char *Templates::ProtoConstructorTemplate = "$classname$($parameter_list$QObject *parent = nullptr) : ProtobufObject(parent)";
 const char *Templates::ConstructorTemplate = "$classname$();\n";
 const char *Templates::CopyConstructorTemplate = "$classname$(const $classname$ &other) : ProtobufObject() {\n";
 const char *Templates::MoveConstructorTemplate = "$classname$($classname$ &&other) : ProtobufObject() {\n";
@@ -123,10 +123,12 @@ const char *Templates::EnumTemplate = "$type$";
 const char *Templates::SimpleBlockEnclosureTemplate = "}\n\n";
 const char *Templates::SemicolonBlockEnclosureTemplate = "};\n";
 const char *Templates::EmptyBlockTemplate = "{}\n\n";
-const char *Templates::ConstructorContentTemplate = "{\n    registerTypes();\n}\n";
+const char *Templates::PropertyInitializerTemplate = "\n    ,m_$property_name$($property_name$)";
+const char *Templates::ConstructorContentTemplate = "\n{\n    registerTypes();\n}\n";
 
 const char *Templates::DeclareMetaTypeTemplate = "Q_DECLARE_METATYPE($namespaces$::$classname$)\n";
 const char *Templates::DeclareComplexListTypeTemplate = "Q_DECLARE_METATYPE($namespaces$::$classname$List)\n";
+const char *Templates::RegisterMetaTypeTemplateNoNamespace = "        qRegisterMetaType<$namespaces$::$classname$>(\"$classname$\");\n";
 const char *Templates::RegisterMetaTypeTemplate = "        qRegisterMetaType<$namespaces$::$classname$>(\"$namespaces$::$classname$\");\n";
 
 const char *Templates::QEnumTemplate = "Q_ENUM($type$)\n";

+ 2 - 0
src/generator/templates.h

@@ -85,10 +85,12 @@ public:
     static const char *SimpleBlockEnclosureTemplate;
     static const char *SemicolonBlockEnclosureTemplate;
     static const char *EmptyBlockTemplate;
+    static const char *PropertyInitializerTemplate;
     static const char *ConstructorContentTemplate;
     static const char *DeclareMetaTypeTemplate;
     static const char *DeclareComplexListTypeTemplate;
     static const char *RegisterMetaTypeTemplate;
+    static const char *RegisterMetaTypeTemplateNoNamespace;
     static const char *QEnumTemplate;
 
     //Service templates

+ 18 - 2
tests/simpletest.cpp

@@ -650,20 +650,36 @@ TEST_F(SimpleTest, SimpleSInt32MapMessage)
 {
     const char* propertyName = "mapField";
     SimpleSInt32MapMessage::registerTypes();
+    SimpleSInt32MapMessage test;
     ASSERT_TRUE(QMetaType::isRegistered(qMetaTypeId<SimpleSInt32MapMessage::MapFieldEntry>()));
     int propertyNumber = SimpleSInt32MapMessage::propertyOrdering.at(1); //See simpletest.proto
-    ASSERT_STREQ(SimpleSInt32MapMessage::staticMetaObject.property(propertyNumber).typeName(), "MapFieldEntry");
+    ASSERT_STREQ(SimpleSInt32MapMessage::staticMetaObject.property(propertyNumber).typeName(), "SimpleSInt32MapMessage::MapFieldEntry");
     ASSERT_EQ(SimpleSInt32MapMessage::staticMetaObject.property(propertyNumber).userType(), qMetaTypeId<SimpleSInt32MapMessage::MapFieldEntry>());
     ASSERT_STREQ(SimpleSInt32MapMessage::staticMetaObject.property(propertyNumber).name(), propertyName);
+    SimpleSInt32MapMessage::MapFieldEntry testMap = {{10, {"Some 10"}}, {0, {"Some 0"}}, {44, {"Some 44"}}};
+    test.setMapField(testMap);
+    ASSERT_TRUE(test.property(propertyName).value<SimpleSInt32MapMessage::MapFieldEntry>() == testMap);
+    ASSERT_TRUE(test.mapField() == testMap);
+    ASSERT_STREQ(test.mapField()[10].testFieldString().toStdString().c_str(), "Some 10");
+    ASSERT_STREQ(test.mapField()[0].testFieldString().toStdString().c_str(), "Some 0");
+    ASSERT_STREQ(test.mapField()[44].testFieldString().toStdString().c_str(), "Some 44");
 }
 
 TEST_F(SimpleTest, SimpleStringMapMessage)
 {
     const char* propertyName = "mapField";
     SimpleStringMapMessage::registerTypes();
+    SimpleStringMapMessage test;
     ASSERT_TRUE(QMetaType::isRegistered(qMetaTypeId<SimpleStringMapMessage::MapFieldEntry>()));
     int propertyNumber = SimpleStringMapMessage::propertyOrdering.at(1); //See simpletest.proto
-    ASSERT_STREQ(SimpleStringMapMessage::staticMetaObject.property(propertyNumber).typeName(), "MapFieldEntry");
+    ASSERT_STREQ(SimpleStringMapMessage::staticMetaObject.property(propertyNumber).typeName(), "SimpleStringMapMessage::MapFieldEntry");
     ASSERT_EQ(SimpleStringMapMessage::staticMetaObject.property(propertyNumber).userType(), qMetaTypeId<SimpleStringMapMessage::MapFieldEntry>());
     ASSERT_STREQ(SimpleStringMapMessage::staticMetaObject.property(propertyNumber).name(), propertyName);
+    SimpleStringMapMessage::MapFieldEntry testMap = {{"key 10", {"Some 10", nullptr}}, {"key 0", {"Some 0", nullptr}}, {"key 44", {"Some 44", nullptr}}};
+    test.setMapField(testMap);
+    ASSERT_TRUE(test.property(propertyName).value<SimpleStringMapMessage::MapFieldEntry>() == testMap);
+    ASSERT_TRUE(test.mapField() == testMap);
+    ASSERT_STREQ(test.mapField()["key 10"].testFieldString().toStdString().c_str(), "Some 10");
+    ASSERT_STREQ(test.mapField()["key 0"].testFieldString().toStdString().c_str(), "Some 0");
+    ASSERT_STREQ(test.mapField()["key 44"].testFieldString().toStdString().c_str(), "Some 44");
 }