Allow using 'optional' fields

Enable 'optional' fields support in Qt generators. This only allows
using 'optional' fields, but doesn't generate the respective logic
that changes the way of fields serialization. All optional fields
are treated as normal fields in this generator version. This step
allows users to move forward with existing protobuf schemes that
contain optional fields.

Pick-to: 6.6
Task-number: QTBUG-114833
Task-number: QTBUG-114962
Change-Id: I8990325f5fe06470742dc7d607141533bd229c24
Reviewed-by: Konrad Kujawa <konrad.kujawa@qt.io>
This commit is contained in:
Alexey Edelev 2023-07-25 15:28:02 +02:00
parent 822d8b12fd
commit bbb19e18e2
7 changed files with 67 additions and 1 deletions

View File

@ -40,7 +40,6 @@ bool QProtobufGenerator::Generate(const FileDescriptor *file,
{
assert(file != nullptr);
assert(generatorContext != nullptr);
return GenerateMessages(file, generatorContext);
}
@ -266,6 +265,7 @@ void QProtobufGenerator::GenerateHeader(const FileDescriptor *file,
}
bool hasOneofFields = false;
bool hasOptionalFields = false;
std::unordered_set<std::string> qtTypesSet;
common::iterateMessages(
file, [&](const Descriptor *message) {
@ -286,12 +286,23 @@ void QProtobufGenerator::GenerateHeader(const FileDescriptor *file,
+ "/" + field->message_type()->name());
qtTypesSet.insert(field->message_type()->file()->package());
}
if (field->has_optional_keyword())
hasOptionalFields = true;
}
});
if (hasOneofFields)
externalIncludes.insert("QtProtobuf/qprotobufoneof.h");
if (hasOptionalFields) {
std::cerr << "WARNING: '" << file->name() << "' contains 'optional' fields.\n"
"\nOptional fields are not supported in this qtprotobufgen version\n"
"The generator disregards the keyword, but generates the regular\n"
"fields instead.\n"
"\nPlease upgrade Qt to the most recent version to get full support\n"
"of the 'optional' fields.\n";
}
for (const auto &qtTypeInclude: qtTypesSet) {
std::string qtTypeLower = qtTypeInclude;
std::transform(qtTypeLower.begin(), qtTypeLower.end(),

View File

@ -29,6 +29,11 @@ bool GeneratorBase::GenerateAll(const std::vector<const FileDescriptor *> &files
return CodeGenerator::GenerateAll(files, parameter, generatorContext, error);
}
uint64_t GeneratorBase::GetSupportedFeatures() const
{
return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL;
}
std::string GeneratorBase::generateBaseName(const FileDescriptor *file, const std::string &name)
{
std::string outFileBasename;

View File

@ -37,6 +37,8 @@ public:
std::string *error) const override;
bool HasGenerateAll() const override { return true; }
uint64_t GetSupportedFeatures() const override;
static void printDisclaimer(::google::protobuf::io::Printer *printer);
void OpenFileNamespaces(const ::google::protobuf::FileDescriptor *file,
google::protobuf::io::Printer *printer) const;

View File

@ -14,6 +14,7 @@ if(TARGET Qt6::qtprotobufgen)
add_subdirectory(converters)
add_subdirectory(duplicated_metatypes)
add_subdirectory(recursive)
add_subdirectory(optional)
if(TARGET Qt6::ProtobufWellKnownTypes)
add_subdirectory(wellknown)
endif()

View File

@ -0,0 +1,24 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
cmake_minimum_required(VERSION 3.16)
project(tst_protobuf_optional LANGUAGES CXX)
find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
endif()
qt_internal_add_test(tst_protobuf_optional
SOURCES
tst_protobuf_optional.cpp
INCLUDE_DIRECTORIES
../shared
LIBRARIES
Qt::Test
Qt::Protobuf
)
qt_autogen_tools_initial_setup(tst_protobuf_optional)
qt6_add_protobuf(tst_protobuf_optional
PROTO_FILES
../../shared/data/proto/optional.proto
)

View File

@ -0,0 +1,14 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include <QTest>
#include <QObject>
class QtProtobufOptionalTest : public QObject
{
Q_OBJECT
};
QTEST_MAIN(QtProtobufOptionalTest)
#include "tst_protobuf_optional.moc"

View File

@ -0,0 +1,9 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
syntax = "proto3";
package qtprotobufnamespace.optional.tests;
message OptionalMessage {
optional sint32 testField = 2;
}