123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- /*
- * MIT License
- *
- * Copyright (c) 2019 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 "singlefilegenerator.h"
- #include "templates.h"
- #include "classgeneratorbase.h"
- #include "protobufclassgenerator.h"
- #include "protobufsourcegenerator.h"
- #include "enumsgenerator.h"
- #include "enumssourcegenerator.h"
- #include "servergenerator.h"
- #include "clientgenerator.h"
- #include "clientsourcegenerator.h"
- #include "utils.h"
- #include "generatoroptions.h"
- #include <iostream>
- #include <set>
- #include <google/protobuf/stubs/logging.h>
- #include <google/protobuf/stubs/common.h>
- #include <google/protobuf/io/printer.h>
- #include <google/protobuf/io/zero_copy_stream.h>
- #include <google/protobuf/descriptor.h>
- using namespace ::QtProtobuf::generator;
- using namespace ::google::protobuf;
- using namespace ::google::protobuf::compiler;
- std::string generateBaseName(const FileDescriptor *file)
- {
- std::vector<std::string> packages;
- utils::split(file->package(), packages, '.');
- std::string outFileBasename = "";
- for (auto package : packages) {
- outFileBasename += package + "/";
- }
- outFileBasename += utils::extractFileName(file->name());
- return outFileBasename;
- }
- SingleFileGenerator::SingleFileGenerator() : GeneratorBase(GeneratorBase::SingleMode)
- {}
- bool SingleFileGenerator::Generate(const FileDescriptor *file,
- const std::string ¶meter,
- GeneratorContext *generatorContext,
- std::string *error) const
- {
- if (file->syntax() != FileDescriptor::SYNTAX_PROTO3) {
- *error = "Invalid proto used. This plugin only supports 'proto3' syntax";
- return false;
- }
- return GenerateMessages(file, parameter, generatorContext, error)
- && GenerateServices(file, parameter, generatorContext, error);
- }
- bool SingleFileGenerator::GenerateMessages(const ::google::protobuf::FileDescriptor *file,
- const std::string &,
- ::google::protobuf::compiler::GeneratorContext *generatorContext,
- std::string *) const {
- if (file->message_type_count() <= 0 && file->enum_type_count() <= 0) {
- return true;
- }
- std::string outFileBasename = generateBaseName(file);
- std::set<std::string> internalIncludes;
- std::set<std::string> externalIncludes;
- std::shared_ptr<io::ZeroCopyOutputStream> outHeader(generatorContext->Open(outFileBasename + Templates::ProtoFileSuffix + ".h"));
- std::shared_ptr<io::ZeroCopyOutputStream> outSource(generatorContext->Open(outFileBasename + Templates::ProtoFileSuffix + ".cpp"));
- std::shared_ptr<::google::protobuf::io::Printer> outHeaderPrinter(new ::google::protobuf::io::Printer(outHeader.get(), '$'));
- std::shared_ptr<::google::protobuf::io::Printer> outSourcePrinter(new ::google::protobuf::io::Printer(outSource.get(), '$'));
- outHeaderPrinter->Print(Templates::DisclaimerTemplate);
- outHeaderPrinter->Print(Templates::PreambleTemplate);
- outHeaderPrinter->Print(Templates::DefaultProtobufIncludesTemplate);
- if (GeneratorOptions::instance().hasQml()) {
- outHeaderPrinter->Print(Templates::QmlProtobufIncludesTemplate);
- }
- outSourcePrinter->Print(Templates::DisclaimerTemplate);
- outSourcePrinter->Print({{"include", outFileBasename + Templates::ProtoFileSuffix}}, Templates::InternalIncludeTemplate);
- externalIncludes.insert("QByteArray");
- externalIncludes.insert("QString");
- for (int i = 0; i < file->dependency_count(); i++) {
- internalIncludes.insert(generateBaseName(file->dependency(i)) + Templates::ProtoFileSuffix);
- }
- for(auto include : externalIncludes) {
- outHeaderPrinter->Print({{"include", include}}, Templates::ExternalIncludeTemplate);
- }
- for(auto include : internalIncludes) {
- outHeaderPrinter->Print({{"include", include}}, Templates::InternalIncludeTemplate);
- }
- if (GeneratorOptions::instance().hasQml()) {
- outSourcePrinter->Print({{"include", "QQmlEngine"}}, Templates::ExternalIncludeTemplate);
- }
- outSourcePrinter->Print({{"namespace", "QtProtobuf"}}, Templates::UsingNamespaceTemplate);
- PackagesList packageList;
- packageList[file->package()].push_back(file);
- for(int i = 0; i < file->enum_type_count(); i++) {
- EnumsGenerator enumGen2(file->enum_type(i),
- outHeaderPrinter);
- enumGen2.run();
- }
- for(int i = 0; i < file->enum_type_count(); i++) {
- auto enumType = file->enum_type(i);
- EnumsSourceGenerator enumSourceGen2(enumType,
- outSourcePrinter);
- enumSourceGen2.run();
- }
- std::vector<std::string> namespaces;
- std::string namespacesColonDelimited;
- utils::split(file->package(), namespaces, '.');
- assert(namespaces.size() > 0);
- for (size_t i = 0; i < namespaces.size(); i++) {
- if (i > 0) {
- namespacesColonDelimited = namespacesColonDelimited.append("::");
- }
- namespacesColonDelimited = namespacesColonDelimited.append(namespaces[i]);
- outHeaderPrinter->Print({{"namespace", namespaces[i]}}, Templates::NamespaceTemplate);
- }
- iterateNonNestedFileds(file, [&outHeaderPrinter](const ::google::protobuf::Descriptor *message){
- std::string qualifiedClassName = utils::upperCaseName(message->name());
- outHeaderPrinter->Print({{"classname", qualifiedClassName}}, Templates::ProtoClassDeclarationTemplate);
- outHeaderPrinter->Print({{"classname", qualifiedClassName}}, Templates::ComplexListTypeUsingTemplate);
- });
- for (size_t i = 0; i < namespaces.size(); i++) {
- outHeaderPrinter->Print(Templates::SimpleBlockEnclosureTemplate);
- }
- iterateNonNestedFileds(file, [&outHeaderPrinter, &outSourcePrinter](const ::google::protobuf::Descriptor *message){
- ProtobufClassGenerator classGen(message,
- outHeaderPrinter);
- classGen.printNamespaces();
- classGen.printComments(message);
- classGen.printClassDeclaration();
- classGen.printProperties();
- classGen.printPrivate();
- classGen.printClassMembers();
- classGen.printPublic();
- classGen.printDestructor();
- classGen.encloseClass();
- classGen.encloseNamespaces();
- classGen.printMetaTypeDeclaration();
- classGen.printMapsMetaTypesDeclaration();
- classGen.printLocalEnumsMetaTypesDeclaration();
- ProtobufSourceGenerator srcGen(message,
- outSourcePrinter);
- srcGen.printNamespaces();
- srcGen.printFieldsOrdering();
- srcGen.printRegisterBody();
- srcGen.printDestructor();
- srcGen.printConstructor();
- srcGen.printCopyFunctionality();
- srcGen.printMoveSemantic();
- srcGen.printComparisonOperators();
- srcGen.printGetters();
- srcGen.encloseNamespaces();
- });
- return true;
- }
- bool SingleFileGenerator::GenerateServices(const ::google::protobuf::FileDescriptor *file,
- const std::string &,
- ::google::protobuf::compiler::GeneratorContext *generatorContext,
- std::string *) const
- {
- if (file->service_count() <= 0) {
- return true;
- }
- std::string outFileBasename = generateBaseName(file);
- std::set<std::string> internalIncludes;
- std::set<std::string> externalIncludes;
- std::shared_ptr<io::ZeroCopyOutputStream> outHeader(generatorContext->Open(outFileBasename + Templates::GrpcFileSuffix + Templates::ProtoFileSuffix + ".h"));
- std::shared_ptr<io::ZeroCopyOutputStream> outSource(generatorContext->Open(outFileBasename + Templates::GrpcFileSuffix + Templates::ProtoFileSuffix + ".cpp"));
- std::shared_ptr<::google::protobuf::io::Printer> outHeaderPrinter(new ::google::protobuf::io::Printer(outHeader.get(), '$'));
- std::shared_ptr<::google::protobuf::io::Printer> outSourcePrinter(new ::google::protobuf::io::Printer(outSource.get(), '$'));
- outHeaderPrinter->Print(Templates::DisclaimerTemplate);
- outHeaderPrinter->Print(Templates::PreambleTemplate);
- outHeaderPrinter->Print(Templates::DefaultProtobufIncludesTemplate);
- if (GeneratorOptions::instance().hasQml()) {
- outHeaderPrinter->Print(Templates::QmlProtobufIncludesTemplate);
- }
- outSourcePrinter->Print(Templates::DisclaimerTemplate);
- outSourcePrinter->Print({{"include", outFileBasename + Templates::GrpcFileSuffix + Templates::ProtoFileSuffix}}, Templates::InternalIncludeTemplate);
- for (int i = 0; i < file->service_count(); i++) {
- const ServiceDescriptor *service = file->service(i);
- for (int i = 0; i < service->method_count(); i++) {
- const MethodDescriptor *method = service->method(i);
- if (method->input_type()->file() != service->file()) {
- internalIncludes.insert(utils::extractFileName(method->input_type()->file()->name()) + Templates::ProtoFileSuffix);
- }
- if (method->output_type()->file() != service->file()) {
- internalIncludes.insert(utils::extractFileName(method->output_type()->file()->name()) + Templates::ProtoFileSuffix);
- }
- }
- }
- externalIncludes.insert("QAbstractGrpcClient");
- externalIncludes.insert("QGrpcAsyncReply");
- externalIncludes.insert("QGrpcSubscription");
- if (file->message_type_count() > 0) {
- internalIncludes.insert(outFileBasename + Templates::ProtoFileSuffix);
- }
- for(auto include : externalIncludes) {
- outHeaderPrinter->Print({{"include", include}}, Templates::ExternalIncludeTemplate);
- }
- for(auto include : internalIncludes) {
- outHeaderPrinter->Print({{"include", include}}, Templates::InternalIncludeTemplate);
- }
- outSourcePrinter->Print({{"namespace", "QtProtobuf"}}, Templates::UsingNamespaceTemplate);
- for (int i = 0; i < file->service_count(); i++) {
- const ServiceDescriptor *service = file->service(i);
- // Serverside descriptor is not in use
- // std::string baseFilename(service->name());
- // utils::tolower(baseFilename);
- // std::string fullFilename = baseFilename + "server.h";
- // ServerGenerator serverGen(service,
- // std::shared_ptr<io::ZeroCopyOutputStream>(generatorContext->Open(fullFilename)));
- // serverGen.run();
- ClientGenerator clientGen(service,
- outHeaderPrinter);
- clientGen.printNamespaces();
- clientGen.printClientClass();
- clientGen.printPublic();
- clientGen.printConstructor();
- clientGen.printClientMethodsDeclaration();
- clientGen.encloseClass();
- clientGen.encloseNamespaces();
- ClientSourceGenerator clientSrcGen(service,
- outSourcePrinter);
- clientSrcGen.printNamespaces();
- clientSrcGen.printConstructor();
- clientSrcGen.printMethods();
- clientSrcGen.encloseNamespaces();
- }
- return true;
- }
|