Parcourir la source

Implement repeated fields types generation

- Add listmodels header with generated list models
- Fix minor issues
Alexey Edelev il y a 6 ans
Parent
commit
2d318f70f3

+ 1 - 2
src/generator/classgeneratorbase.cpp

@@ -74,8 +74,7 @@ bool ClassGeneratorBase::producePropertyMap(const FieldDescriptor* field, Proper
 
 void ClassGeneratorBase::printPreamble()
 {
-    mPrinter.Print("#pragma once\n"
-                   "#include <QObject>\n");
+    mPrinter.Print(PreambleTemplate);
 }
 
 void ClassGeneratorBase::printIncludes(const Descriptor* message)

+ 4 - 3
src/generator/classgeneratorbase.h

@@ -39,14 +39,15 @@ using PropertyMap = std::map<std::string, std::string>;
 
 class ClassGeneratorBase
 {
+public:
+    ClassGeneratorBase(std::string mClassName, std::unique_ptr<::google::protobuf::io::ZeroCopyOutputStream> out);
+
+protected:
     std::unique_ptr<::google::protobuf::io::ZeroCopyOutputStream> mOutput;
     ::google::protobuf::io::Printer mPrinter;
     std::string mClassName;
     int mNamespaceCount;
-public:
-    ClassGeneratorBase(std::string mClassName, std::unique_ptr<::google::protobuf::io::ZeroCopyOutputStream> out);
 
-protected:
     bool producePropertyMap(const ::google::protobuf::FieldDescriptor* field, PropertyMap& propertyMap);
     void printPreamble();
     void printIncludes(const ::google::protobuf::Descriptor* message);

+ 43 - 1
src/generator/generator.cpp

@@ -48,21 +48,42 @@ class QtClassGenerator : public ClassGeneratorBase
 {
     std::string mPackage;
     const Descriptor* mMessage;
+    std::set<std::string> mExtractedModels;
 
 public:
     QtClassGenerator(const std::string& package, const Descriptor* message, std::unique_ptr<io::ZeroCopyOutputStream> out) :
         ClassGeneratorBase(message->name(), std::move(out))
       , mPackage(std::move(package))
-      ,mMessage(message){}
+      , mMessage(message){}
 
     void run() {
+        //Post generation collect all generated model types
+        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();
+                mExtractedModels.insert(typeName);
+            }
+        }
+
         printPreamble();
         printIncludes(mMessage);
+
+        if (mExtractedModels.size() > 0) {
+            mPrinter.Print("\n#include <universallistmodel.h>\n");
+        }
+
         printNamespaces(mPackage);
         printClass();
         printProperties(mMessage);
         enclose();
     }
+
+    const std::set<std::string>& extractedModels() const {
+        return mExtractedModels;
+    }
+
 };
 
 class GlobalEnumsGenerator : public ClassGeneratorBase
@@ -94,6 +115,8 @@ bool QtGenerator::Generate(const FileDescriptor* file,
         return false;
     }
 
+    std::set<std::string> extractedModels;
+
     for(int i = 0; i < file->message_type_count(); i++) {
         const Descriptor* message = file->message_type(i);
         std::string filename = message->name() + ".h";
@@ -101,10 +124,29 @@ bool QtGenerator::Generate(const FileDescriptor* file,
         QtClassGenerator classGen(file->package(), message,
                                   std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generator_context->Open(filename))));
         classGen.run();
+        extractedModels.insert(std::begin(classGen.extractedModels()), std::end(classGen.extractedModels()));
     }
 
     std::string globalEnumsFilename = "globalenums.h";
     GlobalEnumsGenerator enumGen(file, std::move(std::unique_ptr<io::ZeroCopyOutputStream>(generator_context->Open(globalEnumsFilename))));
     enumGen.run();
+
+    //TODO: move to separate class also slipt definitions
+    //Print list models
+    std::unique_ptr<io::ZeroCopyOutputStream> out(generator_context->Open("listmodels.h"));
+    io::Printer printer(out.get(), '$');
+    printer.Print(PreambleTemplate);
+
+    for(auto modelTypeName : extractedModels) {
+        std::string modelTypeNameLower(modelTypeName);
+        std::transform(std::begin(modelTypeNameLower), std::end(modelTypeNameLower), std::begin(modelTypeNameLower), ::tolower);
+        printer.Print({{"type_lower", modelTypeNameLower}}, InternalIncludeTemplate);
+    }
+
+    printer.Print("\n#include <universallistmodel.h>\n");
+    for(auto modelTypeName : extractedModels) {
+        printer.Print({{"type", modelTypeName}}, ModelClassTemplate);
+    }
+
     return true;
 }

+ 5 - 0
src/generator/templates.h

@@ -31,6 +31,10 @@
 
 namespace qtprotobuf {
 
+static const char *PreambleTemplate = "/* This file is autogenerated. DO NOT CHANGE. All changes will be lost */\n\n"
+                                      "#pragma once\n"
+                                     "#include <QObject>\n";
+
 static const char *StartTemplate = "\nclass $classname$ : public QObject\n"
                       "{\n"
                       "    Q_OBJECT\n";
@@ -63,6 +67,7 @@ static const char *InternalIncludeTemplate =  "#include \"$type_lower$.h\"\n";
 static const char *ExternalIncludeTemplate = "#include <$type$>\n";
 
 static const char *EnumTemplate = "$type$";
+static const char *ModelClassTemplate = "using $type$Model = UniversalListModel<$type$>;\n";
 
 static const std::unordered_map<::google::protobuf::FieldDescriptor::Type, std::string> TypeReflection = {
     {::google::protobuf::FieldDescriptor::TYPE_DOUBLE, "qreal"},