Fix detecting of unused nested messages

Previously if nested message was never used by the nesting class it
was ignored to be generated. It was the result if invalid filtering
of map messages as nested types.
Use the explicit map_key() based check instead of weird and tricky
one based on nesting class fields.

Keep the fallback solution that uses MessageOptions when building
with libprotoc versions less than 3.12.

Fixes: QTBUG-115175
Change-Id: I4aa238dac3375bdcdf85e41ba9daef74474ed0fb
Reviewed-by: Tatiana Borisova <tatiana.borisova@qt.io>
(cherry picked from commit 03ccff3aa7)
This commit is contained in:
Alexey Edelev 2023-07-31 18:39:26 +02:00
parent 9f9f34ffcc
commit 32e57bd1ae
5 changed files with 44 additions and 22 deletions

View File

@ -2,6 +2,7 @@
# SPDX-License-Identifier: BSD-3-Clause # SPDX-License-Identifier: BSD-3-Clause
qt_add_library(QtProtocCommon STATIC qt_add_library(QtProtocCommon STATIC
qtprotocdefs.h
baseprinter.cpp baseprinter.h baseprinter.cpp baseprinter.h
descriptorprinterbase.h descriptorprinterbase.h
generatorbase.cpp generatorbase.h generatorbase.cpp generatorbase.h

View File

@ -7,6 +7,12 @@
#include "utils.h" #include "utils.h"
#include "commontemplates.h" #include "commontemplates.h"
#include "qtprotocdefs.h"
#ifndef HAVE_PROTOBUF_SYNC_PIPER
# include <google/protobuf/descriptor.pb.h>
#endif
#include <cassert> #include <cassert>
#include <algorithm> #include <algorithm>
@ -477,41 +483,31 @@ void common::iterateNestedMessages(const Descriptor *message,
int numNestedTypes = message->nested_type_count(); int numNestedTypes = message->nested_type_count();
for (int i = 0; i < numNestedTypes; ++i) { for (int i = 0; i < numNestedTypes; ++i) {
const Descriptor *nestedMessage = message->nested_type(i); const Descriptor *nestedMessage = message->nested_type(i);
if (message->field_count() <= 0) { #ifdef HAVE_PROTOBUF_SYNC_PIPER
if (nestedMessage->map_key() == nullptr) {
#else
if (!nestedMessage->options().map_entry()) {
#endif
callback(nestedMessage); callback(nestedMessage);
continue; continue;
} }
int numFields = message->field_count();
for (int j = 0; j < numFields; ++j) {
const FieldDescriptor *field = message->field(j);
// Probably there is more correct way to detect map in
// nested messages.
// TODO: Have idea to make maps nested classes instead of typedefs.
if (!field->is_map() && field->message_type() == nestedMessage) {
callback(nestedMessage);
break;
}
}
} }
} }
bool common::hasNestedMessages(const Descriptor *message) bool common::hasNestedMessages(const Descriptor *message)
{ {
int numNestedTypes = message->nested_type_count(); int numNestedTypes = message->nested_type_count();
int numFields = message->field_count(); if (numNestedTypes > 0 && message->field_count() == 0)
if (numNestedTypes > 0 && numFields <= 0)
return true; return true;
for (int i = 0; i < numNestedTypes; ++i) { for (int i = 0; i < numNestedTypes; ++i) {
const Descriptor *nestedMessage = message->nested_type(i); const Descriptor *nestedMessage = message->nested_type(i);
for (int j = 0; j < numFields; ++j) { #ifdef HAVE_PROTOBUF_SYNC_PIPER
const FieldDescriptor *field = message->field(j); if (nestedMessage->map_key() == nullptr)
// Probably there is more correct way to detect map in #else
// nested messages. if (!nestedMessage->options().map_entry())
// TODO: Have idea to make maps nested classes instead of typedefs. #endif
if (!field->is_map() && field->message_type() == nestedMessage) return true;
return true;
}
} }
return false; return false;

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
#ifndef QTPROTOCDEFS_H
#define QTPROTOCDEFS_H
#include <google/protobuf/port_def.inc>
#if PROTOBUF_VERSION >= 3012000
// Idicates the major libprotoc API update that happened in version 3.12
# define HAVE_PROTOBUF_SYNC_PIPER
#endif
#include <google/protobuf/port_undef.inc>
#endif // QTPROTOCDEFS_H

View File

@ -10,6 +10,9 @@ message NestedFieldMessage {
message NestedMessage { message NestedMessage {
sint32 testFieldInt = 1; sint32 testFieldInt = 1;
} }
message UnusedNestedMessage {
sint32 testFieldInt = 1;
}
NestedMessage nested = 2; NestedMessage nested = 2;
} }

View File

@ -26,6 +26,7 @@ private slots:
void NeighborTest(); void NeighborTest();
void NestedNoFieldsTest(); void NestedNoFieldsTest();
void NestedCyclingTest(); void NestedCyclingTest();
void UnusedNestedMessageTest();
private: private:
std::unique_ptr<QProtobufSerializer> m_serializer; std::unique_ptr<QProtobufSerializer> m_serializer;
}; };
@ -254,5 +255,12 @@ void QtProtobufNestedTest::NestedCyclingTest()
test2.setTestField(test); test2.setTestField(test);
} }
void QtProtobufNestedTest::UnusedNestedMessageTest()
{
qProtobufAssertMessagePropertyRegistered<NestedFieldMessage::UnusedNestedMessage,
QtProtobuf::sint32>(1, "QtProtobuf::sint32",
"testFieldInt");
}
QTEST_MAIN(QtProtobufNestedTest) QTEST_MAIN(QtProtobufNestedTest)
#include "tst_protobuf_nestedtypes.moc" #include "tst_protobuf_nestedtypes.moc"