Skip to content

Commit

Permalink
Collect extensions with the descriptor pool where the file descriptor…
Browse files Browse the repository at this point in the history
… was built from, instead of with the generated pool.

PiperOrigin-RevId: 705635053
  • Loading branch information
protobuf-github-bot authored and copybara-github committed Dec 12, 2024
1 parent 2de1e7e commit e4c78ee
Showing 1 changed file with 29 additions and 42 deletions.
71 changes: 29 additions & 42 deletions src/google/protobuf/compiler/java/file.cc
Original file line number Diff line number Diff line change
Expand Up @@ -102,44 +102,34 @@ bool CollectExtensions(const Message& message, FieldDescriptorSet* extensions) {
return true;
}

// Finds all extensions in the given message and its sub-messages. If the
// message contains unknown fields (which could be extensions), then those
// extensions are defined in alternate_pool.
// The message will be converted to a DynamicMessage backed by alternate_pool
// in order to handle this case.
void CollectExtensions(const FileDescriptorProto& file_proto,
const DescriptorPool& alternate_pool,
FieldDescriptorSet* extensions,
const std::string& file_data) {
if (!CollectExtensions(file_proto, extensions)) {
// There are unknown fields in the file_proto, which are probably
// extensions. We need to parse the data into a dynamic message based on the
// builder-pool to find out all extensions.
const Descriptor* file_proto_desc = alternate_pool.FindMessageTypeByName(
file_proto.GetDescriptor()->full_name());
ABSL_CHECK(file_proto_desc)
<< "Find unknown fields in FileDescriptorProto when building "
<< file_proto.name()
<< ". It's likely that those fields are custom options, however, "
"descriptor.proto is not in the transitive dependencies. "
"This normally should not happen. Please report a bug.";
DynamicMessageFactory factory;
std::unique_ptr<Message> dynamic_file_proto(
factory.GetPrototype(file_proto_desc)->New());
ABSL_CHECK(dynamic_file_proto.get() != nullptr);
ABSL_CHECK(dynamic_file_proto->ParseFromString(file_data));

// Collect the extensions again from the dynamic message. There should be no
// more unknown fields this time, i.e. all the custom options should be
// parsed as extensions now.
extensions->clear();
ABSL_CHECK(CollectExtensions(*dynamic_file_proto, extensions))
<< "Find unknown fields in FileDescriptorProto when building "
<< file_proto.name()
<< ". It's likely that those fields are custom options, however, "
"those options cannot be recognized in the builder pool. "
"This normally should not happen. Please report a bug.";
}
// Finds all extensions for custom options in the given file descriptor with the
// builder pool which resolves Java features instead of the generated pool.
void CollectExtensions(const FileDescriptor& file,
FieldDescriptorSet* extensions) {
FileDescriptorProto file_proto = StripSourceRetentionOptions(file);
std::string file_data;
file_proto.SerializeToString(&file_data);
const Descriptor* file_proto_desc = file.pool()->FindMessageTypeByName(
file_proto.GetDescriptor()->full_name());

// descriptor.proto is not found in the builder pool, meaning there are no
// custom options.
if (file_proto_desc == nullptr) return;

DynamicMessageFactory factory;
std::unique_ptr<Message> dynamic_file_proto(
factory.GetPrototype(file_proto_desc)->New());
ABSL_CHECK(dynamic_file_proto.get() != nullptr);
ABSL_CHECK(dynamic_file_proto->ParseFromString(file_data));

// Collect the extensions again from the dynamic message.
extensions->clear();
ABSL_CHECK(CollectExtensions(*dynamic_file_proto, extensions))
<< "Found unknown fields in FileDescriptorProto when building "
<< file_proto.name()
<< ". It's likely that those fields are custom options, however, "
"those options cannot be recognized in the builder pool. "
"This normally should not happen. Please report a bug.";
}

// Our static initialization methods can become very, very large.
Expand Down Expand Up @@ -474,11 +464,8 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
// To find those extensions, we need to parse the data into a dynamic message
// of the FileDescriptor based on the builder-pool, then we can use
// reflections to find all extension fields
FileDescriptorProto file_proto = StripSourceRetentionOptions(*file_);
std::string file_data;
file_proto.SerializeToString(&file_data);
FieldDescriptorSet extensions;
CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
CollectExtensions(*file_, &extensions);

if (options_.strip_nonfunctional_codegen) {
// Skip feature extensions, which are a visible (but non-functional)
Expand Down

0 comments on commit e4c78ee

Please sign in to comment.