[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);