Skip to content

Commit 4dec1a7

Browse files
authored
Force descriptor initialization of dependencies *before* internalUpdateFileDescriptor(). (#15718)
This fixes an edge-case where EnumDescriptor for a custom option may be unresolved if used in the same file, since adding the field to ExtensionRegistry doesn't trigger its static init block if the Enum is imported from a dependency. Also renames feature resolution methods exposed from gencode. Private resolveAllFeaturesInternal() method may be renamed back to resolveAllFeatures() in a followup change. PiperOrigin-RevId: 603852391
1 parent 6028cdb commit 4dec1a7

3 files changed

Lines changed: 33 additions & 34 deletions

File tree

java/core/src/main/java/com/google/protobuf/Descriptors.java

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ public FieldDescriptor findExtensionByName(String name) {
348348
* Construct a {@code FileDescriptor}.
349349
*
350350
* @param proto the protocol message form of the FileDescriptort
351-
* @param dependencies {@code FileDescriptor}s corresponding to all of the file's dependencies
351+
* @param dependencies {@code FileDescriptor}s corresponding to all of the file's dependencies.
352352
* @throws DescriptorValidationException {@code proto} is not a valid descriptor. This can occur
353353
* for a number of reasons; for instance, because a field has an undefined type or because
354354
* two messages were defined with the same name.
@@ -397,7 +397,9 @@ private static FileDescriptor buildFrom(
397397
result.crossLink();
398398
// Skip feature resolution until later for calls from gencode.
399399
if (!allowUnresolvedFeatures) {
400-
result.resolveAllFeatures();
400+
// We do not need to force feature resolution for proto1 dependencies
401+
// since dependencies from non-gencode should already be fully feature resolved.
402+
result.resolveAllFeaturesInternal();
401403
}
402404
return result;
403405
}
@@ -480,19 +482,19 @@ public static FileDescriptor internalBuildGeneratedFileFrom(
480482
return internalBuildGeneratedFileFrom(descriptorDataParts, dependencies);
481483
}
482484

483-
/**
484-
* This method is to be called by generated code only. It updates the FileDescriptorProto
485-
* associated with the descriptor by parsing it again with the given ExtensionRegistry. This is
486-
* needed to recognize custom options.
487-
*/
488-
public static void internalUpdateFileDescriptor(
485+
public static void internalUpdateFileDescriptorImmutable(
489486
FileDescriptor descriptor, ExtensionRegistry registry) {
487+
internalUpdateFileDescriptor(descriptor, registry, false);
488+
}
489+
490+
private static void internalUpdateFileDescriptor(
491+
FileDescriptor descriptor, ExtensionRegistry registry, boolean mutable) {
490492
ByteString bytes = descriptor.proto.toByteString();
491493
try {
492494
FileDescriptorProto proto = FileDescriptorProto.parseFrom(bytes, registry);
493495
synchronized (descriptor) {
494496
descriptor.setProto(proto);
495-
descriptor.resolveAllFeatures();
497+
descriptor.resolveAllFeaturesImmutable();
496498
}
497499
} catch (InvalidProtocolBufferException e) {
498500
throw new IllegalArgumentException(
@@ -618,11 +620,15 @@ private FileDescriptor(
618620
pool.addSymbol(message);
619621
}
620622

623+
public void resolveAllFeaturesImmutable() {
624+
resolveAllFeaturesInternal();
625+
}
626+
621627
/**
622628
* This method is to be called by generated code only. It resolves features for the descriptor
623629
* and all of its children.
624630
*/
625-
public void resolveAllFeatures() {
631+
private void resolveAllFeaturesInternal() {
626632
if (this.features != null) {
627633
return;
628634
}

src/google/protobuf/compiler/java/file.cc

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
430430
// Feature resolution for Java features uses extension registry
431431
// which must happen after internalInit() from
432432
// GenerateNonNestedInitializationCode
433-
printer->Print("descriptor.resolveAllFeatures();\n");
433+
printer->Print("descriptor.resolveAllFeaturesImmutable();\n");
434434

435435
// Proto compiler builds a DescriptorPool, which holds all the descriptors to
436436
// generate, when processing the ".proto" files. We call this DescriptorPool
@@ -460,6 +460,17 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
460460
return field->containing_type()->full_name() == "google.protobuf.FeatureSet";
461461
});
462462
}
463+
464+
// Force descriptor initialization of all dependencies.
465+
for (int i = 0; i < file_->dependency_count(); i++) {
466+
if (ShouldIncludeDependency(file_->dependency(i), true)) {
467+
std::string dependency =
468+
name_resolver_->GetImmutableClassName(file_->dependency(i));
469+
printer->Print("$dependency$.getDescriptor();\n", "dependency",
470+
dependency);
471+
}
472+
}
473+
463474
if (!extensions.empty()) {
464475
// Must construct an ExtensionRegistry containing all existing extensions
465476
// and use it to parse the descriptor data again to recognize extensions.
@@ -479,17 +490,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
479490
}
480491
printer->Print(
481492
"com.google.protobuf.Descriptors.FileDescriptor\n"
482-
" .internalUpdateFileDescriptor(descriptor, registry);\n");
483-
}
484-
485-
// Force descriptor initialization of all dependencies.
486-
for (int i = 0; i < file_->dependency_count(); i++) {
487-
if (ShouldIncludeDependency(file_->dependency(i), true)) {
488-
std::string dependency =
489-
name_resolver_->GetImmutableClassName(file_->dependency(i));
490-
printer->Print("$dependency$.getDescriptor();\n", "dependency",
491-
dependency);
492-
}
493+
" .internalUpdateFileDescriptorImmutable(descriptor, registry);\n");
493494
}
494495

495496
printer->Outdent();

src/google/protobuf/compiler/java/shared_code_generator.cc

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,6 @@ void SharedCodeGenerator::Generate(
7676
options_.annotate_code ? info_relative_path : "",
7777
options_);
7878

79-
if (!options_.opensource_runtime) {
80-
printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n");
81-
}
8279

8380
printer->Print(
8481

@@ -87,17 +84,12 @@ void SharedCodeGenerator::Generate(
8784
"returns\n"
8885
" * an incomplete descriptor for internal use only. */\n"
8986
" public static com.google.protobuf.Descriptors.FileDescriptor\n"
90-
" descriptor;\n"
91-
" /* This method is to be called by generated code only. It returns\n"
92-
" * an incomplete descriptor for internal use only. */\n"
93-
" public static com.google.protobuf.Descriptors.FileDescriptor "
94-
"getDescriptor() {\n"
95-
" descriptor.resolveAllFeatures();\n"
96-
" return descriptor;\n"
97-
" }\n"
98-
" static {\n",
87+
" descriptor;\n",
9988
"classname", classname);
10089
printer->Annotate("classname", file_->name());
90+
91+
92+
printer->Print(" static {\n");
10193
printer->Indent();
10294
printer->Indent();
10395
GenerateDescriptors(printer.get());

0 commit comments

Comments
 (0)