diff --git a/protos_generator/gen_enums.cc b/protos_generator/gen_enums.cc index e6f866a0ae..e1ad32b54f 100644 --- a/protos_generator/gen_enums.cc +++ b/protos_generator/gen_enums.cc @@ -25,6 +25,11 @@ #include "protos_generator/gen_enums.h" +#include +#include +#include +#include + #include "google/protobuf/descriptor.pb.h" #include "google/protobuf/descriptor.h" #include "protos_generator/gen_utils.h" @@ -106,10 +111,6 @@ void WriteEnumValues(const protobuf::EnumDescriptor* desc, Output& output) { 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 8e7d6ea678..00c7ca403f 100644 --- a/protos_generator/gen_enums.h +++ b/protos_generator/gen_enums.h @@ -34,6 +34,9 @@ namespace protos_generator { 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& enums, Output& output); void WriteEnumDeclarations( diff --git a/protos_generator/gen_messages.cc b/protos_generator/gen_messages.cc index 194fab0a15..acdbad085b 100644 --- a/protos_generator/gen_messages.cc +++ b/protos_generator/gen_messages.cc @@ -27,9 +27,13 @@ #include "protos_generator/gen_messages.h" +#include +#include + #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 WriteModelAccessDeclaration(const protobuf::Descriptor* descriptor, void WriteModelPublicDeclaration( const protobuf::Descriptor* descriptor, const std::vector& file_exts, + const std::vector& file_enums, Output& output); void WriteExtensionIdentifiersInClassHeader( const protobuf::Descriptor* message, @@ -62,6 +67,10 @@ void WriteExtensionIdentifiersImplementation( const protobuf::Descriptor* message, const std::vector& file_exts, Output& output); +void WriteUsingEnumsInHeader( + const protobuf::Descriptor* message, + const std::vector& file_enums, + Output& output); // Writes message class declarations into .upb.proto.h. // @@ -70,6 +79,7 @@ void WriteExtensionIdentifiersImplementation( void WriteMessageClassDeclarations( const protobuf::Descriptor* descriptor, const std::vector& file_exts, + const std::vector& file_enums, Output& output) { if (IsMapEntryMessage(descriptor)) { // Skip map entry generation. Low level accessors for maps are @@ -85,7 +95,7 @@ void WriteMessageClassDeclarations( 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 WriteModelAccessDeclaration(const protobuf::Descriptor* descriptor, void WriteModelPublicDeclaration( const protobuf::Descriptor* descriptor, const std::vector& file_exts, + const std::vector& file_enums, Output& output) { output( R"cc( @@ -157,6 +168,7 @@ void WriteModelPublicDeclaration( 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 WriteExtensionIdentifiersImplementation( } } +void WriteUsingEnumsInHeader( + const protobuf::Descriptor* message, + const std::vector& 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 0b8aa95f1f..bf0ab7cb6f 100644 --- a/protos_generator/gen_messages.h +++ b/protos_generator/gen_messages.h @@ -37,6 +37,7 @@ namespace protobuf = ::google::protobuf; void WriteMessageClassDeclarations( const protobuf::Descriptor* descriptor, const std::vector& file_exts, + const std::vector& 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 2e5fbd4a2e..255f65a6f4 100644 --- a/protos_generator/protoc-gen-upb-protos.cc +++ b/protos_generator/protoc-gen-upb-protos.cc @@ -171,7 +171,8 @@ void WriteHeader(const protobuf::FileDescriptor* file, Output& output) { 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 d6ca24a00b..a085de00ab 100644 --- a/protos_generator/tests/test_generated.cc +++ b/protos_generator/tests/test_generated.cc @@ -36,6 +36,7 @@ using ::protos_generator::test::protos::other_ext; 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, Enum) { EXPECT_EQ(1, RED); } 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(arena);