Skip to content

Commit ffc067f

Browse files
karenwuzcopybara-github
authored andcommitted
Automated rollback of commit 138b748.
PiperOrigin-RevId: 839825314
1 parent 5b2d67e commit ffc067f

File tree

7 files changed

+252
-63
lines changed

7 files changed

+252
-63
lines changed

‎src/google/protobuf/compiler/command_line_interface_unittest.cc‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2631,7 +2631,8 @@ TEST_F(CommandLineInterfaceTest, JavaMultipleFilesEdition2024Invalid){
26312631
Run("protocol_compiler --proto_path=$tmpdir "
26322632
"foo.proto --test_out=$tmpdir --experimental_editions");
26332633
ExpectErrorSubstring(
2634-
"The `java_multiple_files` behavior is enabled by default");
2634+
"google.protobuf.FileOptions.java_multiple_files has been removed in edition "
2635+
"2024: This behavior is enabled by default");
26352636
}
26362637

26372638

@@ -2645,7 +2646,8 @@ TEST_F(CommandLineInterfaceTest, JavaNestInFileClassFor){
26452646
Run("protocol_compiler --proto_path=$tmpdir "
26462647
"foo.proto --test_out=$tmpdir --experimental_editions");
26472648
ExpectErrorSubstring(
2648-
"The `java_multiple_files` behavior is enabled by default");
2649+
"google.protobuf.FileOptions.java_multiple_files has been removed in edition "
2650+
"2024: This behavior is enabled by default");
26492651
}
26502652

26512653

‎src/google/protobuf/descriptor.cc‎

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1611,8 +1611,9 @@ class DescriptorPool::DeferredValidation{
16111611
}
16121612

16131613
structLifetimesInfo{
1614-
constFeatureSet* proto_features;
1614+
constMessage* option_to_validate; // features or options to validate
16151615
const Message* proto;
1616+
bool is_feature;
16161617
absl::string_view full_name;
16171618
absl::string_view filename;
16181619
};
@@ -1640,16 +1641,19 @@ class DescriptorPool::DeferredValidation{
16401641
if (lifetimes_info_map_.empty()) returntrue;
16411642

16421643
static absl::string_view feature_set_name = "google.protobuf.FeatureSet";
1643-
const Descriptor* feature_set =
1644-
pool_->FindMessageTypeByName(feature_set_name);
1645-
16461644
bool has_errors = false;
16471645
for (constauto& it : lifetimes_info_map_){
16481646
const FileDescriptor* file = it.first;
16491647

16501648
for (constauto& info : it.second){
1649+
const Descriptor* feature_set_descriptor = nullptr;
1650+
// TODO: Support custom options
1651+
if (info.is_feature){
1652+
feature_set_descriptor =
1653+
pool_->FindMessageTypeByName(feature_set_name);
1654+
}
16511655
auto results = FeatureResolver::ValidateFeatureLifetimes(
1652-
file->edition(), *info.proto_features, feature_set);
1656+
file->edition(), *info.option_to_validate, feature_set_descriptor);
16531657
for (constauto& error : results.errors){
16541658
has_errors = true;
16551659
if (error_collector_ == nullptr){
@@ -6227,6 +6231,11 @@ static void PlanAllocationSize(const FileDescriptorProto& proto,
62276231
}
62286232
}
62296233

6234+
template <typename OptionT>
6235+
boolIsDefaultInstance(const OptionT& opt){
6236+
return &opt == &OptionT::default_instance();
6237+
}
6238+
62306239
const FileDescriptor* DescriptorBuilder::BuildFile(
62316240
const FileDescriptorProto& proto){
62326241
// Ensure the generated pool has been lazily initialized. This is most
@@ -6685,10 +6694,17 @@ FileDescriptor* DescriptorBuilder::BuildFileImpl(
66856694
if (!had_errors_ && !pool_->lazily_build_dependencies_){
66866695
internal::VisitDescriptors(
66876696
*result, proto, [&](constauto& descriptor, constauto& desc_proto){
6688-
if (descriptor.proto_features_ != &FeatureSet::default_instance()){
6697+
if (!IsDefaultInstance(*descriptor.proto_features_)){
66896698
deferred_validation_.ValidateFeatureLifetimes(
6690-
GetFile(descriptor),{descriptor.proto_features_, &desc_proto,
6691-
GetFullName(descriptor), proto.name()});
6699+
GetFile(descriptor),
6700+
{descriptor.proto_features_, &desc_proto, /*is_feature=*/true,
6701+
GetFullName(descriptor), proto.name()});
6702+
}
6703+
if (!IsDefaultInstance(*descriptor.options_)){
6704+
deferred_validation_.ValidateFeatureLifetimes(
6705+
GetFile(descriptor),
6706+
{descriptor.options_, &desc_proto,
6707+
/*is_feature=*/false, GetFullName(descriptor), proto.name()});
66926708
}
66936709
});
66946710
}
@@ -8394,13 +8410,6 @@ void DescriptorBuilder::ValidateOptions(const FileDescriptor* file,
83948410
}
83958411

83968412
if (file->edition() >= Edition::EDITION_2024){
8397-
if (file->options().has_java_multiple_files()){
8398-
AddError(file->name(), proto, DescriptorPool::ErrorCollector::OPTION_NAME,
8399-
"The `java_multiple_files` behavior is enabled by default in "
8400-
"editions 2024 and above. To disable it, you can set "
8401-
"`features.(pb.java).nest_in_file_class = YES` on individual "
8402-
"messages, enums, or services.");
8403-
}
84048413
if (file->weak_dependency_count() > 0){
84058414
AddError("weak", proto, DescriptorPool::ErrorCollector::IMPORT,
84068415
"weak imports are not allowed under edition 2024 and beyond.");

‎src/google/protobuf/descriptor_unittest.cc‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12323,6 +12323,49 @@ TEST_F(FeaturesTest, RemovedFeature){
1232312323
"Custom feature removal error\n");
1232412324
}
1232512325

12326+
TEST_F(FeaturesTest, RemovedOption){
12327+
BuildDescriptorMessagesInTestPool();
12328+
BuildFileWithErrors(
12329+
R"pb(
12330+
name: "foo.proto"
12331+
syntax: "editions"
12332+
edition: EDITION_2024
12333+
options{java_multiple_files: true }
12334+
)pb",
12335+
"foo.proto: foo.proto: NAME: "
12336+
"google.protobuf.FileOptions.java_multiple_files has been removed in edition "
12337+
"2024: This behavior is enabled by default in "
12338+
"editions 2024 and above. To disable it, you can set "
12339+
"`features.(pb.java).nest_in_file_class = YES` on individual messages, "
12340+
"enums, or services.\n");
12341+
}
12342+
12343+
TEST_F(FeaturesTest, RemoveOptionAndFeature){
12344+
BuildDescriptorMessagesInTestPool();
12345+
BuildFileInTestPool(pb::TestFeatures::descriptor()->file());
12346+
BuildFileWithErrors(
12347+
R"pb(
12348+
name: "foo.proto"
12349+
syntax: "editions"
12350+
edition: EDITION_2024
12351+
dependency: "google/protobuf/unittest_features.proto"
12352+
options{
12353+
java_multiple_files: true
12354+
features{
12355+
[pb.test]{removed_feature: VALUE9 }
12356+
}
12357+
}
12358+
)pb",
12359+
"foo.proto: foo.proto: NAME: "
12360+
"pb.TestFeatures.removed_feature has been removed in edition 2024: "
12361+
"Custom feature removal error\n"
12362+
"foo.proto: foo.proto: NAME: google.protobuf.FileOptions.java_multiple_files has "
12363+
"been removed in edition 2024: This behavior is enabled by default in "
12364+
"editions 2024 and above. To disable it, you can set "
12365+
"`features.(pb.java).nest_in_file_class = YES` on individual messages, "
12366+
"enums, or services.\n");
12367+
}
12368+
1232612369
TEST_F(FeaturesTest, RemovedFeatureDefault){
1232712370
BuildDescriptorMessagesInTestPool();
1232812371
BuildFileInTestPool(pb::TestFeatures::descriptor()->file());

‎src/google/protobuf/feature_resolver.cc‎

Lines changed: 51 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -399,32 +399,40 @@ void ValidateSingleFeatureLifetimes(
399399
}
400400

401401
voidValidateFeatureLifetimesImpl(Edition edition, const Message& message,
402-
FeatureResolver::ValidationResults& results){
402+
FeatureResolver::ValidationResults& results,
403+
bool is_feature){
403404
std::vector<const FieldDescriptor*> fields;
404405
message.GetReflection()->ListFields(message, &fields);
405406
for (const FieldDescriptor* field : fields){
406-
// Recurse into message extension.
407-
if (field->is_extension() &&
408-
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE){
409-
ValidateFeatureLifetimesImpl(
410-
edition, message.GetReflection()->GetMessage(message, field),
411-
results);
412-
continue;
413-
}
414-
415-
if (field->enum_type() != nullptr){
416-
int number = message.GetReflection()->GetEnumValue(message, field);
417-
auto value = field->enum_type()->FindValueByNumber(number);
418-
if (value == nullptr){
419-
results.errors.emplace_back(absl::StrCat(
420-
"Feature ", field->full_name(), " has no known value ", number));
407+
// TODO: Support repeated option enum values and custom options
408+
// feature support
409+
if (is_feature){
410+
// Recurse into message extension.
411+
if (field->is_extension() &&
412+
field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE){
413+
ValidateFeatureLifetimesImpl(
414+
edition, message.GetReflection()->GetMessage(message, field),
415+
results, is_feature);
421416
continue;
422417
}
423-
ValidateSingleFeatureLifetimes(edition, value->full_name(),
424-
value->options().feature_support(),
425-
results);
426-
}
427418

419+
if (field->enum_type() != nullptr){
420+
int number = message.GetReflection()->GetEnumValue(message, field);
421+
auto value = field->enum_type()->FindValueByNumber(number);
422+
if (value == nullptr){
423+
results.errors.emplace_back(absl::StrCat(
424+
"Feature ", field->full_name(), " has no known value ", number));
425+
continue;
426+
}
427+
ValidateSingleFeatureLifetimes(edition, value->full_name(),
428+
value->options().feature_support(),
429+
results);
430+
}
431+
}
432+
// TODO: Support custom options
433+
if (field->is_extension()){
434+
continue;
435+
}
428436
ValidateSingleFeatureLifetimes(edition, field->full_name(),
429437
field->options().feature_support(), results);
430438
}
@@ -558,30 +566,34 @@ absl::StatusOr<FeatureSet> FeatureResolver::MergeFeatures(
558566
}
559567

560568
FeatureResolver::ValidationResults FeatureResolver::ValidateFeatureLifetimes(
561-
Edition edition, const FeatureSet& features,
562-
const Descriptor* pool_descriptor){
563-
const Message* pool_features = nullptr;
569+
Edition edition, const Message& option, const Descriptor* pool_descriptor){
570+
const Message* pool_option = nullptr;
564571
DynamicMessageFactory factory;
565-
std::unique_ptr<Message> features_storage;
566-
if (pool_descriptor == nullptr){
567-
// The FeatureSet descriptor can be null if no custom extensions are defined
568-
// in any transitive dependency. In this case, we can just use the
569-
// generated pool for validation, since there wouldn't be any feature
570-
// extensions defined anyway.
571-
pool_features = &features;
572-
} else{
573-
// Move the features back to the current pool so that we can reflect on any
574-
// extensions.
575-
features_storage =
572+
std::unique_ptr<Message> message_storage;
573+
bool is_feature =
574+
option.GetDescriptor()->name() == FeatureSet::descriptor()->name();
575+
// TODO: Support custom options
576+
if (pool_descriptor != nullptr && is_feature){
577+
// Move the messages back to the current pool so that we can reflect on
578+
// any extensions.
579+
message_storage =
576580
absl::WrapUnique(factory.GetPrototype(pool_descriptor)->New());
577-
// TODO: Remove this suppression.
578-
(void)features_storage->ParseFromString(features.SerializeAsString());
579-
pool_features = features_storage.get();
581+
// TODO: Remove this suppression
582+
(void)message_storage->ParseFromString(option.SerializeAsString());
583+
pool_option = message_storage.get();
584+
} else{
585+
// The Message descriptor can be null if no custom extensions are
586+
// defined in any transitive dependency. In this case, we can just use
587+
// the generated pool for validation, since there wouldn't be any feature
588+
// extensions defined anyway.
589+
pool_option = &option;
580590
}
581-
ABSL_CHECK(pool_features != nullptr);
591+
ABSL_CHECK(pool_option != nullptr);
582592

583593
ValidationResults results;
584-
ValidateFeatureLifetimesImpl(edition, *pool_features, results);
594+
// Validate feature support
595+
ValidateFeatureLifetimesImpl(edition, *pool_option, results, is_feature);
596+
585597
return results;
586598
}
587599

‎src/google/protobuf/feature_resolver.h‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ class PROTOBUF_EXPORT FeatureResolver{
7070
std::vector<std::string> warnings;
7171
};
7272
static ValidationResults ValidateFeatureLifetimes(
73-
Edition edition, constFeatureSet& features,
73+
Edition edition, constMessage& option,
7474
const Descriptor* pool_descriptor);
7575

7676
private:
@@ -91,4 +91,3 @@ absl::StatusOr<FeatureSet> PROTOBUF_EXPORT GetEditionFeatureSetDefaults(
9191
#include"google/protobuf/port_undef.inc"
9292

9393
#endif// GOOGLE_PROTOBUF_FEATURE_RESOLVER_H__
94-

0 commit comments

Comments
(0)