Automated rollback of commit 63389c027f.

PiperOrigin-RevId: 512087869
pull/12051/head
Adam Cozzette 2 years ago committed by Copybara-Service
parent 0e48352e6d
commit 3942e53072
  1. 77
      python/google/protobuf/internal/generator_test.py
  2. 12
      src/google/protobuf/compiler/python/BUILD.bazel
  3. 100
      src/google/protobuf/compiler/python/generator.cc
  4. 11
      src/google/protobuf/compiler/python/generator.h
  5. 103
      src/google/protobuf/compiler/retention.cc
  6. 22
      src/google/protobuf/compiler/retention.h

@ -49,7 +49,6 @@ from google.protobuf import unittest_import_public_pb2
from google.protobuf import unittest_mset_pb2 from google.protobuf import unittest_mset_pb2
from google.protobuf import unittest_mset_wire_format_pb2 from google.protobuf import unittest_mset_wire_format_pb2
from google.protobuf import unittest_pb2 from google.protobuf import unittest_pb2
from google.protobuf import unittest_retention_pb2
from google.protobuf import unittest_custom_options_pb2 from google.protobuf import unittest_custom_options_pb2
from google.protobuf import unittest_no_generic_services_pb2 from google.protobuf import unittest_no_generic_services_pb2
@ -153,82 +152,6 @@ class GeneratorTest(unittest.TestCase):
# TODO(gps): We really should test for the presence of the enum_opt1 # TODO(gps): We really should test for the presence of the enum_opt1
# extension and for its value to be set to -789. # extension and for its value to be set to -789.
# Options that are explicitly marked RETENTION_SOURCE should not be present
# in the descriptors in the binary.
def testOptionRetention(self):
# Direct options
options = unittest_retention_pb2.DESCRIPTOR.GetOptions()
self.assertTrue(options.HasExtension(unittest_retention_pb2.plain_option))
self.assertTrue(
options.HasExtension(unittest_retention_pb2.runtime_retention_option)
)
self.assertFalse(
options.HasExtension(unittest_retention_pb2.source_retention_option)
)
def check_options_message_is_stripped_correctly(options):
self.assertEqual(options.plain_field, 1)
self.assertEqual(options.runtime_retention_field, 2)
self.assertFalse(options.HasField('source_retention_field'))
self.assertEqual(options.source_retention_field, 0)
# Verify that our test OptionsMessage is stripped correctly on all
# different entity types.
check_options_message_is_stripped_correctly(
options.Extensions[unittest_retention_pb2.file_option]
)
check_options_message_is_stripped_correctly(
unittest_retention_pb2.TopLevelMessage.DESCRIPTOR.GetOptions().Extensions[
unittest_retention_pb2.message_option
]
)
check_options_message_is_stripped_correctly(
unittest_retention_pb2.TopLevelMessage.NestedMessage.DESCRIPTOR.GetOptions().Extensions[
unittest_retention_pb2.message_option
]
)
check_options_message_is_stripped_correctly(
unittest_retention_pb2._TOPLEVELENUM.GetOptions().Extensions[
unittest_retention_pb2.enum_option
]
)
check_options_message_is_stripped_correctly(
unittest_retention_pb2._TOPLEVELMESSAGE_NESTEDENUM.GetOptions().Extensions[
unittest_retention_pb2.enum_option
]
)
check_options_message_is_stripped_correctly(
unittest_retention_pb2._TOPLEVELENUM.values[0]
.GetOptions()
.Extensions[unittest_retention_pb2.enum_entry_option]
)
check_options_message_is_stripped_correctly(
unittest_retention_pb2.DESCRIPTOR.extensions_by_name['i']
.GetOptions()
.Extensions[unittest_retention_pb2.field_option]
)
check_options_message_is_stripped_correctly(
unittest_retention_pb2.TopLevelMessage.DESCRIPTOR.fields[0]
.GetOptions()
.Extensions[unittest_retention_pb2.field_option]
)
check_options_message_is_stripped_correctly(
unittest_retention_pb2.TopLevelMessage.DESCRIPTOR.oneofs[0]
.GetOptions()
.Extensions[unittest_retention_pb2.oneof_option]
)
check_options_message_is_stripped_correctly(
unittest_retention_pb2.DESCRIPTOR.services_by_name['Service']
.GetOptions()
.Extensions[unittest_retention_pb2.service_option]
)
check_options_message_is_stripped_correctly(
unittest_retention_pb2.DESCRIPTOR.services_by_name['Service']
.methods[0]
.GetOptions()
.Extensions[unittest_retention_pb2.method_option]
)
def testNestedTypes(self): def testNestedTypes(self):
self.assertEqual( self.assertEqual(
set(unittest_pb2.TestAllTypes.DESCRIPTOR.nested_types), set(unittest_pb2.TestAllTypes.DESCRIPTOR.nested_types),

@ -28,7 +28,6 @@ cc_library(
deps = [ deps = [
"//src/google/protobuf:protobuf_nowkt", "//src/google/protobuf:protobuf_nowkt",
"//src/google/protobuf/compiler:code_generator", "//src/google/protobuf/compiler:code_generator",
"//src/google/protobuf/compiler:retention",
"@com_google_absl//absl/strings", "@com_google_absl//absl/strings",
"@com_google_absl//absl/synchronization", "@com_google_absl//absl/synchronization",
], ],
@ -62,12 +61,9 @@ pkg_files(
filegroup( filegroup(
name = "test_srcs", name = "test_srcs",
srcs = glob( srcs = glob([
[ "*_test.cc",
"*_test.cc", "*unittest.cc",
"*unittest.cc", ], allow_empty = True),
],
allow_empty = True,
),
visibility = ["//src/google/protobuf/compiler:__pkg__"], visibility = ["//src/google/protobuf/compiler:__pkg__"],
) )

@ -64,7 +64,6 @@
#include "absl/strings/substitute.h" #include "absl/strings/substitute.h"
#include "google/protobuf/compiler/python/helpers.h" #include "google/protobuf/compiler/python/helpers.h"
#include "google/protobuf/compiler/python/pyi_generator.h" #include "google/protobuf/compiler/python/pyi_generator.h"
#include "google/protobuf/compiler/retention.h"
#include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor.h"
#include "google/protobuf/descriptor.pb.h" #include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/io/printer.h" #include "google/protobuf/io/printer.h"
@ -250,7 +249,8 @@ bool Generator::Generate(const FileDescriptor* file,
std::string filename = GetFileName(file, ".py"); std::string filename = GetFileName(file, ".py");
FileDescriptorProto fdp = StripSourceRetentionOptions(*file_); FileDescriptorProto fdp;
file_->CopyTo(&fdp);
fdp.SerializeToString(&file_descriptor_serialized_); fdp.SerializeToString(&file_descriptor_serialized_);
if (!opensource_runtime_ && GeneratingDescriptorProto()) { if (!opensource_runtime_ && GeneratingDescriptorProto()) {
@ -342,7 +342,7 @@ bool Generator::Generate(const FileDescriptor* file,
FixAllDescriptorOptions(); FixAllDescriptorOptions();
// Set serialized_start and serialized_end. // Set serialized_start and serialized_end.
SetSerializedPbInterval(fdp); SetSerializedPbInterval();
printer_->Outdent(); printer_->Outdent();
if (HasGenericServices(file)) { if (HasGenericServices(file)) {
@ -442,8 +442,7 @@ void Generator::PrintFileDescriptor() const {
m["name"] = file_->name(); m["name"] = file_->name();
m["package"] = file_->package(); m["package"] = file_->package();
m["syntax"] = StringifySyntax(file_->syntax()); m["syntax"] = StringifySyntax(file_->syntax());
m["options"] = OptionsValue( m["options"] = OptionsValue(file_->options().SerializeAsString());
StripLocalSourceRetentionOptions(*file_).SerializeAsString());
m["serialized_descriptor"] = absl::CHexEscape(file_descriptor_serialized_); m["serialized_descriptor"] = absl::CHexEscape(file_descriptor_serialized_);
if (GeneratingDescriptorProto()) { if (GeneratingDescriptorProto()) {
printer_->Print("if _descriptor._USE_C_DESCRIPTORS == False:\n"); printer_->Print("if _descriptor._USE_C_DESCRIPTORS == False:\n");
@ -529,8 +528,7 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
" create_key=_descriptor._internal_create_key,\n" " create_key=_descriptor._internal_create_key,\n"
" values=[\n"; " values=[\n";
std::string options_string; std::string options_string;
StripLocalSourceRetentionOptions(enum_descriptor) enum_descriptor.options().SerializeToString(&options_string);
.SerializeToString(&options_string);
printer_->Print(m, enum_descriptor_template); printer_->Print(m, enum_descriptor_template);
printer_->Indent(); printer_->Indent();
printer_->Indent(); printer_->Indent();
@ -683,8 +681,7 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const {
printer_->Outdent(); printer_->Outdent();
printer_->Print("],\n"); printer_->Print("],\n");
std::string options_string; std::string options_string;
StripLocalSourceRetentionOptions(message_descriptor) message_descriptor.options().SerializeToString(&options_string);
.SerializeToString(&options_string);
printer_->Print( printer_->Print(
"serialized_options=$options_value$,\n" "serialized_options=$options_value$,\n"
"is_extendable=$extendable$,\n" "is_extendable=$extendable$,\n"
@ -711,8 +708,7 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const {
m["name"] = desc->name(); m["name"] = desc->name();
m["full_name"] = desc->full_name(); m["full_name"] = desc->full_name();
m["index"] = absl::StrCat(desc->index()); m["index"] = absl::StrCat(desc->index());
options_string = OptionsValue( options_string = OptionsValue(desc->options().SerializeAsString());
StripLocalSourceRetentionOptions(*desc).SerializeAsString());
if (options_string == "None") { if (options_string == "None") {
m["serialized_options"] = ""; m["serialized_options"] = "";
} else { } else {
@ -1054,8 +1050,7 @@ void Generator::PrintEnumValueDescriptor(
// TODO(robinson): Fix up EnumValueDescriptor "type" fields. // TODO(robinson): Fix up EnumValueDescriptor "type" fields.
// More circular references. ::sigh:: // More circular references. ::sigh::
std::string options_string; std::string options_string;
StripLocalSourceRetentionOptions(descriptor) descriptor.options().SerializeToString(&options_string);
.SerializeToString(&options_string);
absl::flat_hash_map<absl::string_view, std::string> m; absl::flat_hash_map<absl::string_view, std::string> m;
m["name"] = descriptor.name(); m["name"] = descriptor.name();
m["index"] = absl::StrCat(descriptor.index()); m["index"] = absl::StrCat(descriptor.index());
@ -1083,7 +1078,7 @@ std::string Generator::OptionsValue(
void Generator::PrintFieldDescriptor(const FieldDescriptor& field, void Generator::PrintFieldDescriptor(const FieldDescriptor& field,
bool is_extension) const { bool is_extension) const {
std::string options_string; std::string options_string;
StripLocalSourceRetentionOptions(field).SerializeToString(&options_string); field.options().SerializeToString(&options_string);
absl::flat_hash_map<absl::string_view, std::string> m; absl::flat_hash_map<absl::string_view, std::string> m;
m["name"] = field.name(); m["name"] = field.name();
m["full_name"] = field.full_name(); m["full_name"] = field.full_name();
@ -1221,17 +1216,21 @@ std::string Generator::InternalPackage() const {
: "google3.net.google.protobuf.python.internal"; : "google3.net.google.protobuf.python.internal";
} }
// Prints descriptor offsets _serialized_start and _serialized_end. // Prints standard constructor arguments serialized_start and serialized_end.
// Args: // Args:
// descriptor_proto: The descriptor proto to have a serialized reference. // descriptor: The cpp descriptor to have a serialized reference.
// proto: A proto
// Example printer output: // Example printer output:
// _globals['_MYMESSAGE']._serialized_start=47 // serialized_start=41,
// _globals['_MYMESSAGE']._serialized_end=76 // serialized_end=43,
template <typename DescriptorProtoT> //
void Generator::PrintSerializedPbInterval( template <typename DescriptorT, typename DescriptorProtoT>
const DescriptorProtoT& descriptor_proto, absl::string_view name) const { void Generator::PrintSerializedPbInterval(const DescriptorT& descriptor,
DescriptorProtoT& proto,
absl::string_view name) const {
descriptor.CopyTo(&proto);
std::string sp; std::string sp;
descriptor_proto.SerializeToString(&sp); proto.SerializeToString(&sp);
int offset = file_descriptor_serialized_.find(sp); int offset = file_descriptor_serialized_.find(sp);
ABSL_CHECK_GE(offset, 0); ABSL_CHECK_GE(offset, 0);
@ -1255,47 +1254,43 @@ void PrintDescriptorOptionsFixingCode(absl::string_view descriptor,
} }
} // namespace } // namespace
// Generates the start and end offsets for each entity in the serialized file void Generator::SetSerializedPbInterval() const {
// descriptor. The file argument must exactly match what was serialized into
// file_descriptor_serialized_, and should already have had any
// source-retention options stripped out. This is important because we need an
// exact byte-for-byte match so that we can successfully find the correct
// offsets in the serialized descriptors.
void Generator::SetSerializedPbInterval(const FileDescriptorProto& file) const {
// Top level enums. // Top level enums.
for (int i = 0; i < file_->enum_type_count(); ++i) { for (int i = 0; i < file_->enum_type_count(); ++i) {
EnumDescriptorProto proto;
const EnumDescriptor& descriptor = *file_->enum_type(i); const EnumDescriptor& descriptor = *file_->enum_type(i);
PrintSerializedPbInterval(file.enum_type(i), PrintSerializedPbInterval(descriptor, proto,
ModuleLevelDescriptorName(descriptor)); ModuleLevelDescriptorName(descriptor));
} }
// Messages. // Messages.
for (int i = 0; i < file_->message_type_count(); ++i) { for (int i = 0; i < file_->message_type_count(); ++i) {
SetMessagePbInterval(file.message_type(i), *file_->message_type(i)); SetMessagePbInterval(*file_->message_type(i));
} }
// Services. // Services.
for (int i = 0; i < file_->service_count(); ++i) { for (int i = 0; i < file_->service_count(); ++i) {
ServiceDescriptorProto proto;
const ServiceDescriptor& service = *file_->service(i); const ServiceDescriptor& service = *file_->service(i);
PrintSerializedPbInterval(file.service(i), PrintSerializedPbInterval(service, proto,
ModuleLevelServiceDescriptorName(service)); ModuleLevelServiceDescriptorName(service));
} }
} }
void Generator::SetMessagePbInterval(const DescriptorProto& message_proto, void Generator::SetMessagePbInterval(const Descriptor& descriptor) const {
const Descriptor& descriptor) const { DescriptorProto message_proto;
PrintSerializedPbInterval(message_proto, PrintSerializedPbInterval(descriptor, message_proto,
ModuleLevelDescriptorName(descriptor)); ModuleLevelDescriptorName(descriptor));
// Nested messages. // Nested messages.
for (int i = 0; i < descriptor.nested_type_count(); ++i) { for (int i = 0; i < descriptor.nested_type_count(); ++i) {
SetMessagePbInterval(message_proto.nested_type(i), SetMessagePbInterval(*descriptor.nested_type(i));
*descriptor.nested_type(i));
} }
for (int i = 0; i < descriptor.enum_type_count(); ++i) { for (int i = 0; i < descriptor.enum_type_count(); ++i) {
EnumDescriptorProto proto;
const EnumDescriptor& enum_des = *descriptor.enum_type(i); const EnumDescriptor& enum_des = *descriptor.enum_type(i);
PrintSerializedPbInterval(message_proto.enum_type(i), PrintSerializedPbInterval(enum_des, proto,
ModuleLevelDescriptorName(enum_des)); ModuleLevelDescriptorName(enum_des));
} }
} }
@ -1303,8 +1298,7 @@ void Generator::SetMessagePbInterval(const DescriptorProto& message_proto,
// Prints expressions that set the options field of all descriptors. // Prints expressions that set the options field of all descriptors.
void Generator::FixAllDescriptorOptions() const { void Generator::FixAllDescriptorOptions() const {
// Prints an expression that sets the file descriptor's options. // Prints an expression that sets the file descriptor's options.
std::string file_options = OptionsValue( std::string file_options = OptionsValue(file_->options().SerializeAsString());
StripLocalSourceRetentionOptions(*file_).SerializeAsString());
if (file_options != "None") { if (file_options != "None") {
PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_); PrintDescriptorOptionsFixingCode(kDescriptorKey, file_options, printer_);
} else { } else {
@ -1332,8 +1326,7 @@ void Generator::FixAllDescriptorOptions() const {
} }
void Generator::FixOptionsForOneof(const OneofDescriptor& oneof) const { void Generator::FixOptionsForOneof(const OneofDescriptor& oneof) const {
std::string oneof_options = std::string oneof_options = OptionsValue(oneof.options().SerializeAsString());
OptionsValue(StripLocalSourceRetentionOptions(oneof).SerializeAsString());
if (oneof_options != "None") { if (oneof_options != "None") {
std::string oneof_name = absl::Substitute( std::string oneof_name = absl::Substitute(
"$0.$1['$2']", ModuleLevelDescriptorName(*oneof.containing_type()), "$0.$1['$2']", ModuleLevelDescriptorName(*oneof.containing_type()),
@ -1346,15 +1339,15 @@ void Generator::FixOptionsForOneof(const OneofDescriptor& oneof) const {
// value descriptors. // value descriptors.
void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const { void Generator::FixOptionsForEnum(const EnumDescriptor& enum_descriptor) const {
std::string descriptor_name = ModuleLevelDescriptorName(enum_descriptor); std::string descriptor_name = ModuleLevelDescriptorName(enum_descriptor);
std::string enum_options = OptionsValue( std::string enum_options =
StripLocalSourceRetentionOptions(enum_descriptor).SerializeAsString()); OptionsValue(enum_descriptor.options().SerializeAsString());
if (enum_options != "None") { if (enum_options != "None") {
PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_); PrintDescriptorOptionsFixingCode(descriptor_name, enum_options, printer_);
} }
for (int i = 0; i < enum_descriptor.value_count(); ++i) { for (int i = 0; i < enum_descriptor.value_count(); ++i) {
const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i); const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(i);
std::string value_options = OptionsValue( std::string value_options =
StripLocalSourceRetentionOptions(value_descriptor).SerializeAsString()); OptionsValue(value_descriptor.options().SerializeAsString());
if (value_options != "None") { if (value_options != "None") {
PrintDescriptorOptionsFixingCode( PrintDescriptorOptionsFixingCode(
absl::StrFormat("%s.values_by_name[\"%s\"]", descriptor_name.c_str(), absl::StrFormat("%s.values_by_name[\"%s\"]", descriptor_name.c_str(),
@ -1370,8 +1363,8 @@ void Generator::FixOptionsForService(
const ServiceDescriptor& service_descriptor) const { const ServiceDescriptor& service_descriptor) const {
std::string descriptor_name = std::string descriptor_name =
ModuleLevelServiceDescriptorName(service_descriptor); ModuleLevelServiceDescriptorName(service_descriptor);
std::string service_options = OptionsValue( std::string service_options =
StripLocalSourceRetentionOptions(service_descriptor).SerializeAsString()); OptionsValue(service_descriptor.options().SerializeAsString());
if (service_options != "None") { if (service_options != "None") {
PrintDescriptorOptionsFixingCode(descriptor_name, service_options, PrintDescriptorOptionsFixingCode(descriptor_name, service_options,
printer_); printer_);
@ -1379,8 +1372,8 @@ void Generator::FixOptionsForService(
for (int i = 0; i < service_descriptor.method_count(); ++i) { for (int i = 0; i < service_descriptor.method_count(); ++i) {
const MethodDescriptor* method = service_descriptor.method(i); const MethodDescriptor* method = service_descriptor.method(i);
std::string method_options = OptionsValue( std::string method_options =
StripLocalSourceRetentionOptions(*method).SerializeAsString()); OptionsValue(method->options().SerializeAsString());
if (method_options != "None") { if (method_options != "None") {
std::string method_name = absl::StrCat( std::string method_name = absl::StrCat(
descriptor_name, ".methods_by_name['", method->name(), "']"); descriptor_name, ".methods_by_name['", method->name(), "']");
@ -1392,8 +1385,7 @@ void Generator::FixOptionsForService(
// Prints expressions that set the options for field descriptors (including // Prints expressions that set the options for field descriptors (including
// extensions). // extensions).
void Generator::FixOptionsForField(const FieldDescriptor& field) const { void Generator::FixOptionsForField(const FieldDescriptor& field) const {
std::string field_options = std::string field_options = OptionsValue(field.options().SerializeAsString());
OptionsValue(StripLocalSourceRetentionOptions(field).SerializeAsString());
if (field_options != "None") { if (field_options != "None") {
std::string field_name; std::string field_name;
if (field.is_extension()) { if (field.is_extension()) {
@ -1438,8 +1430,8 @@ void Generator::FixOptionsForMessage(const Descriptor& descriptor) const {
FixOptionsForField(field); FixOptionsForField(field);
} }
// Message option for this message. // Message option for this message.
std::string message_options = OptionsValue( std::string message_options =
StripLocalSourceRetentionOptions(descriptor).SerializeAsString()); OptionsValue(descriptor.options().SerializeAsString());
if (message_options != "None") { if (message_options != "None") {
std::string descriptor_name = ModuleLevelDescriptorName(descriptor); std::string descriptor_name = ModuleLevelDescriptorName(descriptor);
PrintDescriptorOptionsFixingCode(descriptor_name, message_options, PrintDescriptorOptionsFixingCode(descriptor_name, message_options,

@ -41,7 +41,6 @@
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h" #include "absl/synchronization/mutex.h"
#include "google/protobuf/compiler/code_generator.h" #include "google/protobuf/compiler/code_generator.h"
#include "google/protobuf/descriptor.pb.h"
// Must be included last. // Must be included last.
#include "google/protobuf/port_def.inc" #include "google/protobuf/port_def.inc"
@ -167,8 +166,9 @@ class PROTOC_EXPORT Generator : public CodeGenerator {
std::string PublicPackage() const; std::string PublicPackage() const;
std::string InternalPackage() const; std::string InternalPackage() const;
template <typename DescriptorProtoT> template <typename DescriptorT, typename DescriptorProtoT>
void PrintSerializedPbInterval(const DescriptorProtoT& descriptor_proto, void PrintSerializedPbInterval(const DescriptorT& descriptor,
DescriptorProtoT& proto,
absl::string_view name) const; absl::string_view name) const;
void FixAllDescriptorOptions() const; void FixAllDescriptorOptions() const;
@ -178,9 +178,8 @@ class PROTOC_EXPORT Generator : public CodeGenerator {
void FixOptionsForService(const ServiceDescriptor& descriptor) const; void FixOptionsForService(const ServiceDescriptor& descriptor) const;
void FixOptionsForMessage(const Descriptor& descriptor) const; void FixOptionsForMessage(const Descriptor& descriptor) const;
void SetSerializedPbInterval(const FileDescriptorProto& file) const; void SetSerializedPbInterval() const;
void SetMessagePbInterval(const DescriptorProto& message_proto, void SetMessagePbInterval(const Descriptor& descriptor) const;
const Descriptor& descriptor) const;
void CopyPublicDependenciesAliases(absl::string_view copy_from, void CopyPublicDependenciesAliases(absl::string_view copy_from,
const FileDescriptor* file) const; const FileDescriptor* file) const;

@ -42,7 +42,6 @@ namespace protobuf {
namespace compiler { namespace compiler {
namespace { namespace {
// Recursively strips any options with source retention from the message. // Recursively strips any options with source retention from the message.
void StripMessage(Message& m) { void StripMessage(Message& m) {
const Reflection* reflection = m.GetReflection(); const Reflection* reflection = m.GetReflection();
@ -63,107 +62,43 @@ void StripMessage(Message& m) {
} }
} }
} }
} // namespace
// Converts the descriptor to a dynamic message if necessary, and then strips FileDescriptorProto StripSourceRetentionOptions(const FileDescriptor& file) {
// out all source-retention options. FileDescriptorProto file_proto;
// file.CopyTo(&file_proto);
// The options message may have custom options set on it, and these would
// ordinarily appear as unknown fields since they are not linked into protoc. // We need to look up the descriptor in file.pool() so that we can get a
// Using a dynamic message allows us to see these custom options. To convert
// back and forth between the generated type and the dynamic message, we have
// to serialize one and parse that into the other.
void ConvertToDynamicMessageAndStripOptions(Message& m,
const DescriptorPool& pool) {
// We need to look up the descriptor in the pool so that we can get a
// descriptor which knows about any custom options that were used in the // descriptor which knows about any custom options that were used in the
// .proto file. // .proto file.
const Descriptor* descriptor = pool.FindMessageTypeByName(m.GetTypeName()); const Descriptor* descriptor =
file.pool()->FindMessageTypeByName(FileDescriptorProto().GetTypeName());
if (descriptor == nullptr) { if (descriptor == nullptr) {
// If the pool does not contain the descriptor, then this proto file does // If the pool does not contain the descriptor for FileDescriptorProto,
// not transitively depend on descriptor.proto, in which case we know there // then this proto file does not transitively depend on descriptor.proto,
// are no custom options to worry about. // in which case we know there are no custom options to worry about.
StripMessage(m); StripMessage(file_proto);
} else { } else {
// The options message may have custom options set on it, and these would
// ordinarily appear as unknown fields since they are not linked into
// protoc. Using a dynamic message allows us to see these custom options.
// To convert back and forth between the generated type and the dynamic
// message, we have to serialize one and parse that into the other.
DynamicMessageFactory factory; DynamicMessageFactory factory;
std::unique_ptr<Message> dynamic_message( std::unique_ptr<Message> dynamic_message(
factory.GetPrototype(descriptor)->New()); factory.GetPrototype(descriptor)->New());
std::string serialized; std::string serialized;
ABSL_CHECK(m.SerializeToString(&serialized)); ABSL_CHECK(file_proto.SerializeToString(&serialized));
ABSL_CHECK(dynamic_message->ParseFromString(serialized)); ABSL_CHECK(dynamic_message->ParseFromString(serialized));
StripMessage(*dynamic_message); StripMessage(*dynamic_message);
ABSL_CHECK(dynamic_message->SerializeToString(&serialized)); ABSL_CHECK(dynamic_message->SerializeToString(&serialized));
ABSL_CHECK(m.ParseFromString(serialized)); ABSL_CHECK(file_proto.ParseFromString(serialized));
} }
}
// Returns a const reference to the descriptor pool associated with the given
// descriptor.
template <typename DescriptorType>
const google::protobuf::DescriptorPool& GetPool(const DescriptorType& descriptor) {
return *descriptor.file()->pool();
}
// Specialization for FileDescriptor.
const google::protobuf::DescriptorPool& GetPool(const FileDescriptor& descriptor) {
return *descriptor.pool();
}
// Returns the options associated with the given descriptor, with all
// source-retention options stripped out.
template <typename DescriptorType>
auto StripLocalOptions(const DescriptorType& descriptor) {
auto options = descriptor.options();
ConvertToDynamicMessageAndStripOptions(options, GetPool(descriptor));
return options;
}
} // namespace
FileDescriptorProto StripSourceRetentionOptions(const FileDescriptor& file) {
FileDescriptorProto file_proto;
file.CopyTo(&file_proto);
ConvertToDynamicMessageAndStripOptions(file_proto, *file.pool());
return file_proto; return file_proto;
} }
EnumOptions StripLocalSourceRetentionOptions(const EnumDescriptor& descriptor) {
return StripLocalOptions(descriptor);
}
EnumValueOptions StripLocalSourceRetentionOptions(
const EnumValueDescriptor& descriptor) {
return StripLocalOptions(descriptor);
}
FieldOptions StripLocalSourceRetentionOptions(
const FieldDescriptor& descriptor) {
return StripLocalOptions(descriptor);
}
FileOptions StripLocalSourceRetentionOptions(const FileDescriptor& descriptor) {
return StripLocalOptions(descriptor);
}
MessageOptions StripLocalSourceRetentionOptions(const Descriptor& descriptor) {
return StripLocalOptions(descriptor);
}
MethodOptions StripLocalSourceRetentionOptions(
const MethodDescriptor& descriptor) {
return StripLocalOptions(descriptor);
}
OneofOptions StripLocalSourceRetentionOptions(
const OneofDescriptor& descriptor) {
return StripLocalOptions(descriptor);
}
ServiceOptions StripLocalSourceRetentionOptions(
const ServiceDescriptor& descriptor) {
return StripLocalOptions(descriptor);
}
} // namespace compiler } // namespace compiler
} // namespace protobuf } // namespace protobuf
} // namespace google } // namespace google

@ -46,28 +46,6 @@ namespace compiler {
PROTOC_EXPORT FileDescriptorProto PROTOC_EXPORT FileDescriptorProto
StripSourceRetentionOptions(const FileDescriptor& file); StripSourceRetentionOptions(const FileDescriptor& file);
// The following functions take a descriptor and strip all source-retention
// options from just the local entity (e.g. message, enum, field). Most code
// generators should not need these functions, but they are sometimes useful if
// you need to strip the options on a single entity rather than handling the
// entire file at once.
PROTOC_EXPORT EnumOptions
StripLocalSourceRetentionOptions(const EnumDescriptor& descriptor);
PROTOC_EXPORT EnumValueOptions
StripLocalSourceRetentionOptions(const EnumValueDescriptor& descriptor);
PROTOC_EXPORT FieldOptions
StripLocalSourceRetentionOptions(const FieldDescriptor& descriptor);
PROTOC_EXPORT FileOptions
StripLocalSourceRetentionOptions(const FileDescriptor& descriptor);
PROTOC_EXPORT MessageOptions
StripLocalSourceRetentionOptions(const Descriptor& descriptor);
PROTOC_EXPORT MethodOptions
StripLocalSourceRetentionOptions(const MethodDescriptor& descriptor);
PROTOC_EXPORT OneofOptions
StripLocalSourceRetentionOptions(const OneofDescriptor& descriptor);
PROTOC_EXPORT ServiceOptions
StripLocalSourceRetentionOptions(const ServiceDescriptor& descriptor);
} // namespace compiler } // namespace compiler
} // namespace protobuf } // namespace protobuf
} // namespace google } // namespace google

Loading…
Cancel
Save