// Copyright (C) 2022 The Qt Company Ltd. // Copyright (C) 2019 Alexey Edelev // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "generatorbase.h" #include #include #include #include #include "utils.h" #include "commontemplates.h" #include "generatorcommon.h" #include "options.h" #include using namespace ::google::protobuf; using namespace ::google::protobuf::io; using namespace ::google::protobuf::compiler; using namespace ::qtprotoccommon; bool GeneratorBase::GenerateAll(const std::vector &files, const std::string ¶meter, GeneratorContext *generatorContext, std::string *error) const { assert(!files.empty()); assert(generatorContext != nullptr); Options::setFromString(parameter, Options::QtProtobufGen, error); if (!error->empty()) return false; if (Options::instance().generateMacroExportFile()) { std::string exportMacroName = Options::instance().exportMacro(); std::string exportMacroFilename = Options::instance().exportMacroFilename(); assert(!exportMacroName.empty()); assert(!exportMacroFilename.empty()); std::unique_ptr headerStream(generatorContext ->Open(exportMacroFilename)); std::shared_ptr headerPrinter(new Printer(headerStream.get(), '$')); printDisclaimer(headerPrinter.get()); headerPrinter->Print({ { "export_macro", exportMacroName } }, CommonTemplates::ExportMacroTemplate()); headerPrinter->PrintRaw("\n"); } if (!Options::instance().extraNamespace().empty()) { std::set extraNamespaceFiles; for (const FileDescriptor *file : files) { assert(file != nullptr); extraNamespaceFiles.insert(std::string{ file->name() }); } common::setExtraNamespacedFiles(extraNamespaceFiles); } return CodeGenerator::GenerateAll(files, parameter, generatorContext, error); } void GeneratorBase::printDisclaimer(Printer *printer) { printer->Print(CommonTemplates::DisclaimerTemplate()); } void GeneratorBase::OpenFileNamespaces( const FileDescriptor *file, google::protobuf::io::Printer *printer) const { assert(printer != nullptr); assert(file != nullptr); const bool hasQtNamespace = (Options::instance().extraNamespace() == "QT_NAMESPACE"); const std::string scopeNamespaces = common::getFullNamespace(std::string{ file->package() } + ".noop", "::", true); printer->Print("\n"); if (hasQtNamespace || file->package() == "QtCore" || file->package() == "QtGui") printer->PrintRaw("QT_BEGIN_NAMESPACE\n"); if (!scopeNamespaces.empty()) { printer->Print({ { "scope_namespaces", scopeNamespaces } }, CommonTemplates::NamespaceTemplate()); } } void GeneratorBase::CloseFileNamespaces( const ::google::protobuf::FileDescriptor *file, google::protobuf::io::Printer *printer) const { assert(printer != nullptr); const bool hasQtNamespace = (Options::instance().extraNamespace() == "QT_NAMESPACE"); const std::string scopeNamespaces = common::getFullNamespace(std::string{ file->package() } + ".noop", "::", true); if (!scopeNamespaces.empty()) { printer->Print({ { "scope_namespaces", scopeNamespaces } }, CommonTemplates::NamespaceClosingTemplate()); } if (hasQtNamespace || file->package() == "QtCore" || file->package() == "QtGui") printer->PrintRaw("QT_END_NAMESPACE\n"); printer->Print("\n"); } void GeneratorBase::printIncludes(google::protobuf::io::Printer *printer, const std::set &internal, const utils::ExternalIncludesOrderedSet &external, const std::set &system) { if (!internal.empty()) printer->Print("\n"); for (const auto &header : internal) printer->Print({ {"include", header } }, CommonTemplates::InternalIncludeTemplate()); std::string_view includeFirstPart; for (const auto &header : external) { const auto firstPartPos = header.find_first_of('/'); if (firstPartPos == std::string::npos) { includeFirstPart = {}; printer->Print("\n"); } else if (std::string_view currentIncludeFirstPart(header.data(), firstPartPos); currentIncludeFirstPart != includeFirstPart) { includeFirstPart = currentIncludeFirstPart; printer->Print("\n"); } printer->Print({ {"include", header } }, CommonTemplates::ExternalIncludeTemplate()); } if (!system.empty()) printer->Print("\n"); for (const auto &header : system) printer->Print({ {"include", header } }, CommonTemplates::ExternalIncludeTemplate()); } void GeneratorBase::printHeaderGuardBegin(google::protobuf::io::Printer *printer, const std::string &guard) { switch (Options::instance().headerGuard()) { case Options::HeaderGuardType::Pragma: printer->Print(CommonTemplates::PragmaOnce()); break; default: printer->Print({ { "header_guard", guard } }, CommonTemplates::HeaderGuardBeginTemplate()); break; } } void GeneratorBase::printHeaderGuardEnd(google::protobuf::io::Printer *printer, const std::string &guard) { if (Options::instance().headerGuard() == Options::HeaderGuardType::Pragma) return; printer->Print({ { "header_guard", guard } }, CommonTemplates::HeaderGuardEndTemplate()); }