Browse Source

Add namespace code for lists and enums from extarnal packages.

- Implement namespace prepending for external types
- Add and update tests
Tatyana Borisova 6 years ago
parent
commit
21151fe7ad

+ 48 - 8
src/generator/protobufclassgenerator.cpp

@@ -212,21 +212,61 @@ void ProtobufClassGenerator::printField(const FieldDescriptor *field, const char
     }
 }
 
+template<typename T>
+std::string ProtobufClassGenerator::getNamespacesList(const T *message, std::vector<std::string> &container)
+{
+    std::string result;
+    utils::split(std::string(message->full_name()), container, '.');
+
+    if (container.size() > 1) {
+        //delete type name -> only namespace stays
+        container.pop_back();
+
+        for (size_t i = 0; i < container.size(); i++) {
+            if (i > 0) {
+                result = result.append("::");
+            }
+            result = result.append(container[i]);
+        }
+    }
+
+    if (container.size() > 0
+            && mNamespacesColonDelimited != result) {
+        result = result.append("::");
+    } else {
+        result.clear();
+    }
+
+    return result;
+}
+
 std::string ProtobufClassGenerator::getTypeName(const FieldDescriptor *field)
 {
     assert(field != nullptr);
     std::string typeName;
-    std::string namespaceDefinition("qtprotobuf::");
+    std::string namespaceQtProtoDefinition("qtprotobuf::");
+
+    std::string namespaceTypeName;
+    std::vector<std::string> typeNamespace;
+
+    if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
+        namespaceTypeName = getNamespacesList(field->message_type(), typeNamespace);
+    } else if (field->type() == FieldDescriptor::TYPE_ENUM) {
+        namespaceTypeName = getNamespacesList(field->enum_type(), typeNamespace);
+    }
+
     if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
-        typeName = field->message_type()->name();
+        typeName = namespaceTypeName.append(field->message_type()->name());
+
         if (field->is_repeated()) {
-            return typeName.append("List");
+            return namespaceTypeName.append("List");
         }
     } else if (field->type() == FieldDescriptor::TYPE_ENUM) {
-        typeName = field->enum_type()->name();
         if (getEnumVisibility(field) == GLOBAL_ENUM) {
             std::string globEnum(Templates::EnumClassNameTemplate);
-            typeName = globEnum.append("::").append(typeName);
+            typeName = namespaceTypeName.append(globEnum.append("::").append(field->enum_type()->name()));
+        } else {
+            typeName = typeName.append(field->enum_type()->name());
         }
         if (field->is_repeated()) {
             return typeName.append("List");
@@ -239,15 +279,15 @@ std::string ProtobufClassGenerator::getTypeName(const FieldDescriptor *field)
                     && field->type() != FieldDescriptor::TYPE_BOOL
                     && field->type() != FieldDescriptor::TYPE_FLOAT
                     && field->type() != FieldDescriptor::TYPE_DOUBLE) {
-                typeName = namespaceDefinition.append(it->second);
+                typeName = typeName.append(namespaceQtProtoDefinition.append(it->second));
             } else {
-                typeName = it->second;
+                typeName = typeName.append(it->second);
             }
             if (field->is_repeated()) {
                 if(field->type() == FieldDescriptor::TYPE_FLOAT
                         || field->type() == FieldDescriptor::TYPE_DOUBLE) {
                     typeName[0] = ::toupper(typeName[0]);
-                    typeName = namespaceDefinition.append(typeName);
+                    typeName = namespaceQtProtoDefinition.append(typeName);
                 }
                 typeName.append("List");
             }

+ 4 - 0
src/generator/protobufclassgenerator.h

@@ -80,6 +80,10 @@ private:
     bool producePropertyMap(const ::google::protobuf::FieldDescriptor *field, PropertyMap &propertyMap);
     static bool isComplexType(const ::google::protobuf::FieldDescriptor *field);
     static bool isListType(const ::google::protobuf::FieldDescriptor *field);
+
+private:
+    template<typename T>
+    std::string getNamespacesList(const T *message, std::vector<std::string> &container);
 };
 
 }

+ 19 - 0
tests/proto/extrenalpackagetest.proto

@@ -0,0 +1,19 @@
+syntax = "proto3";
+
+package qtprotobufnamespace1.externaltests;
+
+message SimpleExternalMessage {
+    repeated int32 localList = 1;
+}
+
+message ExternalComplexMessage {
+    SimpleExternalMessage testFieldInt = 1;
+}
+
+enum ExternalTestEnum {
+    EXTERNAL_TEST_ENUM_VALUE0 = 0;
+    EXTERNAL_TEST_ENUM_VALUE1 = 1;
+    EXTERNAL_TEST_ENUM_VALUE2 = 2;
+    EXTERNAL_TEST_ENUM_VALUE3 = 3;
+    EXTERNAL_TEST_ENUM_VALUE4 = 4;
+}

+ 11 - 0
tests/proto/simpletest.proto

@@ -1,5 +1,7 @@
 syntax = "proto3";
 
+import "extrenalpackagetest.proto";
+
 package qtprotobufnamespace.tests;
 
 message SimpleEnumMessage {
@@ -24,6 +26,10 @@ message SimpleFileEnumMessage {
 //  repeated SimpleEnumMessage.LocalEnum localStepChildList = 2;
 //}
 
+message SimpleExternalEnumMessage {
+    qtprotobufnamespace1.externaltests.ExternalTestEnum externalEnum = 1;
+}
+
 message SimpleBoolMessage {
     bool testFieldBool = 1;
 }
@@ -113,6 +119,11 @@ message RepeatedComplexMessage {
     repeated ComplexMessage testRepeatedComplex = 1;
 }
 
+message RepeatedExternalComplexMessage {
+    repeated qtprotobufnamespace1.externaltests.ExternalComplexMessage testExternalComplex = 1;
+}
+
+
 enum TestEnum {
     TEST_ENUM_VALUE0 = 0;
     TEST_ENUM_VALUE1 = 1;

+ 40 - 0
tests/simpletest.cpp

@@ -41,6 +41,8 @@
 #include "simplefloatmessage.h"
 #include "simpledoublemessage.h"
 #include "simpleenummessage.h"
+#include "simpleexternalenummessage.h"
+#include "externalcomplexmessage.h"
 #include "complexmessage.h"
 #include "simplebytesmessage.h"
 #include "repeatedintmessage.h"
@@ -261,6 +263,31 @@ TEST_F(SimpleTest, SimpleLocalEnumsTest)
     ASSERT_EQ(simpleEnum.value(3), 3);
 }
 
+TEST_F(SimpleTest, SimpleExternalEnumMessage)
+{
+    ASSERT_GT(SimpleExternalEnumMessage::staticMetaObject.enumeratorCount(), 0);
+    QMetaEnum simpleExternalEnum;
+    for (int i = 0; i < SimpleExternalEnumMessage::staticMetaObject.enumeratorCount(); i++) {
+        QMetaEnum tmp = SimpleExternalEnumMessage::staticMetaObject.enumerator(i);
+        if (QString(tmp.name()) == QString("ExternalTestEnum")) {
+            simpleExternalEnum = tmp;
+            break;
+        }
+    }
+    ASSERT_TRUE(simpleExternalEnum.isValid());
+    ASSERT_STREQ(simpleExternalEnum.key(0), "EXTERNAL_TEST_ENUM_VALUE0");
+    ASSERT_STREQ(simpleExternalEnum.key(1), "EXTERNAL_TEST_ENUM_VALUE1");
+    ASSERT_STREQ(simpleExternalEnum.key(2), "EXTERNAL_TEST_ENUM_VALUE2");
+    ASSERT_STREQ(simpleExternalEnum.key(3), "EXTERNAL_TEST_ENUM_VALUE3");
+    ASSERT_STREQ(simpleExternalEnum.key(4), "EXTERNAL_TEST_ENUM_VALUE4");
+
+    ASSERT_EQ(simpleExternalEnum.value(0), 0);
+    ASSERT_EQ(simpleExternalEnum.value(1), 1);
+    ASSERT_EQ(simpleExternalEnum.value(2), 2);
+    ASSERT_EQ(simpleExternalEnum.value(3), 3);
+    ASSERT_EQ(simpleExternalEnum.value(4), 4);
+}
+
 TEST_F(SimpleTest, SimpleEnumsTest)
 {
     ASSERT_GT(GlobalEnums::staticMetaObject.enumeratorCount(), 0);
@@ -303,6 +330,19 @@ TEST_F(SimpleTest, SimpleBytesMessageTest)
     ASSERT_TRUE(test.testFieldBytes() == QByteArray("\x01\x02\x03\x04\x05"));
 }
 
+TEST_F(SimpleTest, SimpleExternalComplexMessageTest)
+{
+    const char* propertyName = "localList";
+    qtprotobufnamespace1::externaltests::SimpleExternalMessage test;
+    int propertyNumber = qtprotobufnamespace1::externaltests::SimpleExternalMessage::propertyOrdering.at(1);
+    ASSERT_STREQ(qtprotobufnamespace1::externaltests::SimpleExternalMessage::staticMetaObject.property(propertyNumber).typeName(), "qtprotobuf::int32List");
+    ASSERT_EQ(qtprotobufnamespace1::externaltests::SimpleExternalMessage::staticMetaObject.property(propertyNumber).userType(), qMetaTypeId<qtprotobuf::int32List>());
+    ASSERT_STREQ(qtprotobufnamespace1::externaltests::SimpleExternalMessage::staticMetaObject.property(propertyNumber).name(), propertyName);
+    ASSERT_TRUE(test.setProperty(propertyName, QVariant::fromValue<int32List>({1, 2, 3, 4, 5})));
+    ASSERT_TRUE(test.property(propertyName).value<int32List>() == int32List({1, 2, 3, 4, 5}));
+    ASSERT_TRUE(test.localList() == int32List({1, 2, 3, 4, 5}));
+}
+
 TEST_F(SimpleTest, RepeatedIntMessageTest)
 {
     const char* propertyName = "testRepeatedInt";