[Upb C++] Generate class scoped declarations for enumerations.
PiperOrigin-RevId: 512191989
diff --git a/protos_generator/gen_enums.cc b/protos_generator/gen_enums.cc
index e6f866a..e1ad32b 100644
--- a/protos_generator/gen_enums.cc
+++ b/protos_generator/gen_enums.cc
@@ -25,6 +25,11 @@
#include "protos_generator/gen_enums.h"
+#include <algorithm>
+#include <limits>
+#include <string>
+#include <vector>
+
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/descriptor.h"
#include "protos_generator/gen_utils.h"
@@ -106,10 +111,6 @@
for (size_t i = 0; i < values.size(); i++) {
auto value = values[i];
output(" $0", EnumValueSymbolInNameSpace(desc, value));
- if (value->options().deprecated()) {
- output(" ABSL_DEPRECATED(\"Proto enum $0\")",
- EnumValueSymbolInNameSpace(desc, value));
- }
output(" = $0", EnumInt32ToString(value->number()));
if (i != values.size() - 1) {
output(",");
diff --git a/protos_generator/gen_enums.h b/protos_generator/gen_enums.h
index 8e7d6ea..00c7ca4 100644
--- a/protos_generator/gen_enums.h
+++ b/protos_generator/gen_enums.h
@@ -34,6 +34,9 @@
namespace protobuf = ::google::protobuf;
std::string EnumTypeName(const protobuf::EnumDescriptor* enum_descriptor);
+std::string EnumValueSymbolInNameSpace(
+ const protobuf::EnumDescriptor* desc,
+ const protobuf::EnumValueDescriptor* value);
void WriteHeaderEnumForwardDecls(
std::vector<const protobuf::EnumDescriptor*>& enums, Output& output);
void WriteEnumDeclarations(
diff --git a/protos_generator/gen_messages.cc b/protos_generator/gen_messages.cc
index 194fab0..acdbad0 100644
--- a/protos_generator/gen_messages.cc
+++ b/protos_generator/gen_messages.cc
@@ -27,9 +27,13 @@
#include "protos_generator/gen_messages.h"
+#include <string>
+#include <vector>
+
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/descriptor.h"
#include "protos_generator/gen_accessors.h"
+#include "protos_generator/gen_enums.h"
#include "protos_generator/gen_extensions.h"
#include "protos_generator/gen_utils.h"
#include "protos_generator/output.h"
@@ -45,6 +49,7 @@
void WriteModelPublicDeclaration(
const protobuf::Descriptor* descriptor,
const std::vector<const protobuf::FieldDescriptor*>& file_exts,
+ const std::vector<const protobuf::EnumDescriptor*>& file_enums,
Output& output);
void WriteExtensionIdentifiersInClassHeader(
const protobuf::Descriptor* message,
@@ -62,6 +67,10 @@
const protobuf::Descriptor* message,
const std::vector<const protobuf::FieldDescriptor*>& file_exts,
Output& output);
+void WriteUsingEnumsInHeader(
+ const protobuf::Descriptor* message,
+ const std::vector<const protobuf::EnumDescriptor*>& file_enums,
+ Output& output);
// Writes message class declarations into .upb.proto.h.
//
@@ -70,6 +79,7 @@
void WriteMessageClassDeclarations(
const protobuf::Descriptor* descriptor,
const std::vector<const protobuf::FieldDescriptor*>& file_exts,
+ const std::vector<const protobuf::EnumDescriptor*>& file_enums,
Output& output) {
if (IsMapEntryMessage(descriptor)) {
// Skip map entry generation. Low level accessors for maps are
@@ -85,7 +95,7 @@
WriteInternalForwardDeclarationsInHeader(descriptor, output);
output("\n");
output("} // namespace internal\n");
- WriteModelPublicDeclaration(descriptor, file_exts, output);
+ WriteModelPublicDeclaration(descriptor, file_exts, file_enums, output);
output("namespace internal {\n");
WriteModelProxyDeclaration(descriptor, output);
WriteModelCProxyDeclaration(descriptor, output);
@@ -131,6 +141,7 @@
void WriteModelPublicDeclaration(
const protobuf::Descriptor* descriptor,
const std::vector<const protobuf::FieldDescriptor*>& file_exts,
+ const std::vector<const protobuf::EnumDescriptor*>& file_enums,
Output& output) {
output(
R"cc(
@@ -157,6 +168,7 @@
ClassName(descriptor));
WriteUsingAccessorsInHeader(descriptor, MessageClassType::kMessage, output);
+ WriteUsingEnumsInHeader(descriptor, file_enums, output);
WriteDefaultInstanceHeader(descriptor, output);
WriteExtensionIdentifiersInClassHeader(descriptor, file_exts, output);
output.Indent();
@@ -376,4 +388,42 @@
}
}
+void WriteUsingEnumsInHeader(
+ const protobuf::Descriptor* message,
+ const std::vector<const protobuf::EnumDescriptor*>& file_enums,
+ Output& output) {
+ for (auto* enum_descriptor : file_enums) {
+ std::string enum_type_name = EnumTypeName(enum_descriptor);
+ std::string enum_resolved_type_name =
+ enum_descriptor->file()->package().empty() &&
+ enum_descriptor->containing_type() == nullptr
+ ? absl::StrCat(kNoPackageNamePrefix,
+ ToCIdent(enum_descriptor->name()))
+ : enum_type_name;
+ if (enum_descriptor->containing_type() == nullptr ||
+ enum_descriptor->containing_type()->full_name() !=
+ message->full_name()) {
+ continue;
+ }
+ output("using $0", enum_descriptor->name());
+ if (enum_descriptor->options().deprecated()) {
+ output(" ABSL_DEPRECATED(\"Proto enum $0\")", enum_descriptor->name());
+ }
+ output(" = $0;", enum_resolved_type_name);
+ output("\n");
+ int value_count = enum_descriptor->value_count();
+ for (int i = 0; i < value_count; i++) {
+ output("static constexpr $0 $1", enum_descriptor->name(),
+ enum_descriptor->value(i)->name());
+ if (enum_descriptor->options().deprecated() ||
+ enum_descriptor->value(i)->options().deprecated()) {
+ output(" ABSL_DEPRECATED(\"Proto enum value $0\") ",
+ enum_descriptor->value(i)->name());
+ }
+ output(" = $0;\n", EnumValueSymbolInNameSpace(enum_descriptor,
+ enum_descriptor->value(i)));
+ }
+ }
+}
+
} // namespace protos_generator
diff --git a/protos_generator/gen_messages.h b/protos_generator/gen_messages.h
index 0b8aa95..bf0ab7c 100644
--- a/protos_generator/gen_messages.h
+++ b/protos_generator/gen_messages.h
@@ -37,6 +37,7 @@
void WriteMessageClassDeclarations(
const protobuf::Descriptor* descriptor,
const std::vector<const protobuf::FieldDescriptor*>& file_exts,
+ const std::vector<const protobuf::EnumDescriptor*>& file_enums,
Output& output);
void WriteMessageImplementation(
const protobuf::Descriptor* descriptor,
diff --git a/protos_generator/protoc-gen-upb-protos.cc b/protos_generator/protoc-gen-upb-protos.cc
index 2e5fbd4..255f65a 100644
--- a/protos_generator/protoc-gen-upb-protos.cc
+++ b/protos_generator/protoc-gen-upb-protos.cc
@@ -171,7 +171,8 @@
output("\n");
for (auto message : this_file_messages) {
- WriteMessageClassDeclarations(message, this_file_exts, output);
+ WriteMessageClassDeclarations(message, this_file_exts, this_file_enums,
+ output);
}
output("\n");
diff --git a/protos_generator/tests/test_generated.cc b/protos_generator/tests/test_generated.cc
index d6ca24a..a085de0 100644
--- a/protos_generator/tests/test_generated.cc
+++ b/protos_generator/tests/test_generated.cc
@@ -36,6 +36,7 @@
using ::protos_generator::test::protos::RED;
using ::protos_generator::test::protos::TestEnum;
using ::protos_generator::test::protos::TestModel;
+using ::protos_generator::test::protos::TestModel_Category;
using ::protos_generator::test::protos::TestModel_Category_IMAGES;
using ::protos_generator::test::protos::TestModel_Category_NEWS;
using ::protos_generator::test::protos::TestModel_Category_VIDEO;
@@ -52,6 +53,16 @@
TEST(CppGeneratedCode, EnumNoPackage) { EXPECT_EQ(1, ::protos_CELSIUS); }
+TEST(CppGeneratedCode, MessageEnumType) {
+ TestModel_Category category1 = TestModel_Category_IMAGES;
+ TestModel::Category category2 = TestModel::IMAGES;
+ EXPECT_EQ(category1, category2);
+}
+
+TEST(CppGeneratedCode, MessageEnumValue) {
+ EXPECT_EQ(TestModel_Category_IMAGES, TestModel::IMAGES);
+}
+
TEST(CppGeneratedCode, ArenaConstructor) {
::protos::Arena arena;
auto testModel = ::protos::CreateMessage<TestModel>(arena);