123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452 |
- /*
- * MIT License
- *
- * Copyright (c) 2020 Alexey Edelev <semlanik@gmail.com>, Tatyana Borisova <tanusshhka@mail.ru>
- *
- * 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 "messagedeclarationprinter.h"
- #include "utils.h"
- #include "generatoroptions.h"
- #include "generatorcommon.h"
- #include <iostream>
- #include <google/protobuf/descriptor.h>
- #include <google/protobuf/descriptor.pb.h>
- using namespace ::QtProtobuf::generator;
- using namespace ::google::protobuf;
- using namespace ::google::protobuf::io;
- using namespace ::google::protobuf::compiler;
- MessageDeclarationPrinter::MessageDeclarationPrinter(const Descriptor *message, const std::shared_ptr<::google::protobuf::io::Printer> &printer)
- : DescriptorPrinterBase<google::protobuf::Descriptor>(message, printer)
- {
- mTypeMap = common::produceMessageTypeMap(message, nullptr);
- }
- void MessageDeclarationPrinter::printClassForwardDeclarationPrivate()
- {
- if (common::hasNestedMessages(mDescriptor)) {
- mPrinter->Print({{"namespace", mTypeMap["classname"] + Templates::QtProtobufNestedNamespace}}, Templates::NamespaceTemplate);
- common::iterateNestedMessages(mDescriptor, [this](const ::google::protobuf::Descriptor *nestedMessage) {
- MessageDeclarationPrinter nesterPrinter(nestedMessage, mPrinter);
- nesterPrinter.printClassForwardDeclarationPrivate();
- });
- mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
- }
- mPrinter->Print(mTypeMap, Templates::ProtoClassForwardDeclarationTemplate);
- mPrinter->Print(mTypeMap, Templates::ComplexListTypeUsingTemplate);
- }
- void MessageDeclarationPrinter::printClassForwardDeclaration()
- {
- printNamespaces();
- printClassForwardDeclarationPrivate();
- encloseNamespaces();
- }
- void MessageDeclarationPrinter::printClassDeclaration()
- {
- printNamespaces();
- printClassDeclarationPrivate();
- encloseNamespaces();
- printMetaTypesDeclaration();//Meta types declaration should be outside of namespaces block
- }
- void MessageDeclarationPrinter::printClassDeclarationPrivate()
- {
- if (common::hasNestedMessages(mDescriptor)) {
- mPrinter->Print({{"namespace", mTypeMap["classname"] + Templates::QtProtobufNestedNamespace}}, Templates::NamespaceTemplate);
- common::iterateNestedMessages(mDescriptor, [this](const ::google::protobuf::Descriptor *nestedMessage) {
- MessageDeclarationPrinter nesterPrinter(nestedMessage, mPrinter);
- nesterPrinter.printClassDeclarationPrivate();
- });
- mPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
- }
- printComments(mDescriptor);
- printClassDeclarationBegin();
- printClassBody();
- encloseClass();
- }
- void MessageDeclarationPrinter::printCopyFunctionality()
- {
- assert(mDescriptor != nullptr);
- mPrinter->Print(mTypeMap,
- Templates::CopyConstructorDeclarationTemplate);
- mPrinter->Print(mTypeMap,
- Templates::AssignmentOperatorDeclarationTemplate);
- }
- void MessageDeclarationPrinter::printMoveSemantic()
- {
- assert(mDescriptor != nullptr);
- mPrinter->Print(mTypeMap,
- Templates::MoveConstructorDeclarationTemplate);
- mPrinter->Print(mTypeMap,
- Templates::MoveAssignmentOperatorDeclarationTemplate);
- }
- void MessageDeclarationPrinter::printComparisonOperators()
- {
- assert(mDescriptor != nullptr);
- mPrinter->Print(mTypeMap, Templates::EqualOperatorDeclarationTemplate);
- mPrinter->Print(mTypeMap, Templates::NotEqualOperatorDeclarationTemplate);
- }
- void MessageDeclarationPrinter::printConstructors()
- {
- for (int i = 0; i <= mDescriptor->field_count(); i++) {
- printConstructor(i);
- }
- if (mDescriptor->full_name() == std::string("google.protobuf.Timestamp")) {
- mPrinter->Print("Timestamp(const QDateTime &datetime, QObject *parent = nullptr);\n"
- "operator QDateTime() const;\n");
- }
- }
- void MessageDeclarationPrinter::printConstructor(int fieldCount)
- {
- std::vector<std::string> parameterList;
- mPrinter->Print(mTypeMap, Templates::ProtoConstructorBeginTemplate);
- for (int i = 0; i < fieldCount; i++) {
- const FieldDescriptor *field = mDescriptor->field(i);
- 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, mDescriptor), parameterTemplate);
- }
- mPrinter->Print(mTypeMap, Templates::ProtoConstructorEndTemplate);
- }
- void MessageDeclarationPrinter::printMaps()
- {
- Indent();
- for (int i = 0; i < mDescriptor->field_count(); i++) {
- const FieldDescriptor *field = mDescriptor->field(i);
- if (field->is_map()) {
- 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, mDescriptor), mapTemplate);
- }
- }
- Outdent();
- }
- void MessageDeclarationPrinter::printNested()
- {
- Indent();
- common::iterateNestedMessages(mDescriptor, [&](const ::google::protobuf::Descriptor *nestedMessage) {
- mPrinter->Print(common::produceMessageTypeMap(nestedMessage, mDescriptor), Templates::NestedMessageUsingTemplate);
- });
- Outdent();
- }
- void MessageDeclarationPrinter::printClassDeclarationBegin()
- {
- mPrinter->Print(mTypeMap, Templates::ProtoClassDeclarationBeginTemplate);
- }
- void MessageDeclarationPrinter::printMetaTypesDeclaration()
- {
- mPrinter->Print(mTypeMap,
- Templates::DeclareMetaTypeTemplate);
- mPrinter->Print(mTypeMap,
- Templates::DeclareComplexListTypeTemplate);
- if (GeneratorOptions::instance().hasQml()) {
- mPrinter->Print(mTypeMap,
- Templates::DeclareComplexQmlListTypeTemplate);
- }
- common::iterateMessageFields(mDescriptor, [&](const FieldDescriptor *field, PropertyMap &propertyMap) {
- if (field->type() == FieldDescriptor::TYPE_ENUM
- && common::isLocalEnum(field->enum_type(), mDescriptor)) {
- mPrinter->Print(propertyMap, Templates::DeclareMetaTypeTemplate);
- mPrinter->Print(propertyMap, Templates::DeclareMetaTypeListTemplate);
- } else if (field->is_map()) {
- propertyMap["key_type_underscore"] = propertyMap["key_type"];
- utils::replace(propertyMap["key_type_underscore"], "::", "_");
- propertyMap["value_type_underscore"] = propertyMap["key_type"];
- utils::replace(propertyMap["value_type_underscore"], "::", "_");
- mPrinter->Print(propertyMap, Templates::DeclareMetaTypeMapTemplate);
- }
- });
- common::iterateNestedMessages(mDescriptor, [this](const Descriptor *nestedMessage) {
- MessageDeclarationPrinter nesterPrinter(nestedMessage, mPrinter);
- nesterPrinter.printMetaTypesDeclaration();
- });
- }
- void MessageDeclarationPrinter::printProperties()
- {
- assert(mDescriptor != nullptr);
- //private section
- Indent();
- for (int i = 0; i < mDescriptor->field_count(); i++) {
- const FieldDescriptor *field = mDescriptor->field(i);
- const char *propertyTemplate = Templates::PropertyTemplate;
- if (common::isPureMessage(field)) {
- propertyTemplate = Templates::MessagePropertyTemplate;
- } else if (common::hasQmlAlias(field)) {
- propertyTemplate = Templates::NonScriptablePropertyTemplate;
- } else if (field->is_repeated() && !field->is_map()) {
- // Non-message list properties don't require an extra QQmlListProperty to access
- // their data, so the property name should not contain the 'Data' suffix
- if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
- propertyTemplate = Templates::RepeatedMessagePropertyTemplate;
- } else {
- propertyTemplate = Templates::RepeatedPropertyTemplate;
- }
- }
- mPrinter->Print(common::producePropertyMap(field, mDescriptor), propertyTemplate);
- }
- //Generate extra QmlListProperty that is mapped to list
- for (int i = 0; i < mDescriptor->field_count(); i++) {
- const FieldDescriptor *field = mDescriptor->field(i);
- if (field->type() == FieldDescriptor::TYPE_MESSAGE && field->is_repeated() && !field->is_map()
- && GeneratorOptions::instance().hasQml()) {
- mPrinter->Print(common::producePropertyMap(field, mDescriptor), Templates::QmlListPropertyTemplate);
- } else if (common::hasQmlAlias(field)) {
- mPrinter->Print(common::producePropertyMap(field, mDescriptor), Templates::NonScriptableAliasPropertyTemplate);
- }
- }
- Outdent();
- }
- void MessageDeclarationPrinter::printGetters()
- {
- Indent();
- common::iterateMessageFields(mDescriptor, [&](const FieldDescriptor *field, const PropertyMap &propertyMap) {
- printComments(field);
- mPrinter->Print("\n");
- if (common::isPureMessage(field)) {
- mPrinter->Print(propertyMap, Templates::GetterMessageDeclarationTemplate);
- } else {
- mPrinter->Print(propertyMap, Templates::GetterTemplate);
- }
- if (field->is_repeated()) {
- mPrinter->Print(propertyMap, Templates::GetterContainerExtraTemplate);
- if (field->type() == FieldDescriptor::TYPE_MESSAGE && !field->is_map()
- && GeneratorOptions::instance().hasQml()) {
- mPrinter->Print(propertyMap, Templates::GetterQmlListDeclarationTemplate);
- }
- }
- });
- Outdent();
- }
- void MessageDeclarationPrinter::printSetters()
- {
- Indent();
- common::iterateMessageFields(mDescriptor, [&](const FieldDescriptor *field, const PropertyMap &propertyMap) {
- switch (field->type()) {
- case FieldDescriptor::TYPE_MESSAGE:
- if (!field->is_map() && !field->is_repeated() && !common::isQtType(field)) {
- mPrinter->Print(propertyMap, Templates::SetterTemplateDeclarationMessageType);
- } else {
- mPrinter->Print(propertyMap, Templates::SetterTemplateDeclarationComplexType);
- }
- break;
- case FieldDescriptor::FieldDescriptor::TYPE_STRING:
- case FieldDescriptor::FieldDescriptor::TYPE_BYTES:
- mPrinter->Print(propertyMap, Templates::SetterTemplateDeclarationComplexType);
- break;
- default:
- mPrinter->Print(propertyMap, Templates::SetterTemplate);
- break;
- }
- });
- Outdent();
- }
- void MessageDeclarationPrinter::printPrivateGetters()
- {
- Indent();
- common::iterateMessageFields(mDescriptor, [&](const FieldDescriptor *field, const PropertyMap &propertyMap) {
- if (common::isPureMessage(field)) {
- mPrinter->Print(propertyMap, Templates::GetterPrivateMessageDeclarationTemplate);
- }
- });
- Outdent();
- }
- void MessageDeclarationPrinter::printPrivateSetters()
- {
- Indent();
- common::iterateMessageFields(mDescriptor, [&](const FieldDescriptor *field, const PropertyMap &propertyMap) {
- if (common::isPureMessage(field)) {
- mPrinter->Print(propertyMap, Templates::SetterPrivateTemplateDeclarationMessageType);
- }
- });
- Outdent();
- }
- void MessageDeclarationPrinter::printSignals()
- {
- Indent();
- for (int i = 0; i < mDescriptor->field_count(); i++) {
- mPrinter->Print(common::producePropertyMap(mDescriptor->field(i), mDescriptor), Templates::SignalTemplate);
- }
- Outdent();
- }
- void MessageDeclarationPrinter::printPrivateMethods()
- {
- Indent();
- common::iterateMessageFields(mDescriptor, [&](const FieldDescriptor *field, const PropertyMap &propertyMap) {
- if (common::hasQmlAlias(field)) {
- mPrinter->Print(propertyMap, Templates::NonScriptableGetterTemplate);
- mPrinter->Print(propertyMap, Templates::NonScriptableSetterTemplate);
- }
- });
- Outdent();
- }
- void MessageDeclarationPrinter::printQEnums() {
- if (GeneratorOptions::instance().generateFieldEnum()) {
- printFieldEnum();
- Indent();
- mPrinter->Print({{"type", Templates::QtProtobufFieldEnum}}, Templates::QEnumTemplate);
- Outdent();
- mPrinter->Print("\n");
- }
- if (mDescriptor->enum_type_count() <= 0) {
- return;
- }
- Indent();
- for (int i = 0; i < mDescriptor->enum_type_count(); i++) {
- const auto enumDescr = mDescriptor->enum_type(i);
- auto typeMap = common::produceEnumTypeMap(enumDescr, mDescriptor);
- mPrinter->Print(typeMap, Templates::EnumDefinitionTemplate);
- Indent();
- for (int j = 0; j < enumDescr->value_count(); j++) {
- const auto valueDescr = enumDescr->value(j);
- mPrinter->Print({{"enumvalue", utils::upperCaseName(valueDescr->name())},
- {"value", std::to_string(valueDescr->number())}}, Templates::EnumFieldTemplate);
- }
- Outdent();
- mPrinter->Print(Templates::SemicolonBlockEnclosureTemplate);
- mPrinter->Print(typeMap, Templates::QEnumTemplate);
- }
- for (int i = 0; i < mDescriptor->enum_type_count(); i++) {
- const auto enumDescr = mDescriptor->enum_type(i);
- auto typeMap = common::produceEnumTypeMap(enumDescr, mDescriptor);
- mPrinter->Print(typeMap, Templates::EnumTypeRepeatedTemplate);
- }
- Outdent();
- }
- void MessageDeclarationPrinter::printClassBody()
- {
- printProperties();
- printPublicBlock();
- printQEnums();
- printNested();
- printMaps();
- Indent();
- printConstructors();
- printDestructor();
- printCopyFunctionality();
- printMoveSemantic();
- printComparisonOperators();
- Outdent();
- printGetters();
- printSetters();
- Indent();
- mPrinter->Print(mTypeMap, Templates::ManualRegistrationDeclaration);
- Outdent();
- printSignalsBlock();
- printSignals();
- printPrivateBlock();
- printPrivateGetters();
- printPrivateSetters();
- printPrivateMethods();
- printPrivateBlock();
- printClassMembers();
- }
- void MessageDeclarationPrinter::printClassMembers()
- {
- Indent();
- common::iterateMessageFields(mDescriptor, [&](const FieldDescriptor *field, const PropertyMap &propertyMap) {
- if (common::isPureMessage(field)) {
- mPrinter->Print(propertyMap, Templates::ComplexMemberTemplate);
- } else if (field->is_repeated() && !field->is_map()) {
- mPrinter->Print(propertyMap, Templates::ListMemberTemplate);
- } else {
- mPrinter->Print(propertyMap, Templates::MemberTemplate);
- }
- });
- Outdent();
- }
- void MessageDeclarationPrinter::printDestructor()
- {
- mPrinter->Print(mTypeMap, "virtual ~$classname$();\n");
- }
- void MessageDeclarationPrinter::printFieldEnum()
- {
- Indent();
- mPrinter->Print(Templates::FieldEnumTemplate);
- Indent();
- common::iterateMessageFields(mDescriptor, [&](const FieldDescriptor *, const PropertyMap &propertyMap) {
- mPrinter->Print(propertyMap, Templates::FieldNumberTemplate);
- });
- Outdent();
- mPrinter->Print(Templates::SemicolonBlockEnclosureTemplate);
- Outdent();
- }
|