diff --git a/java/core/src/main/resources/google/protobuf/java_features.proto b/java/core/src/main/resources/google/protobuf/java_features.proto index 0ec9ac2fd1d6..d73c2c1eb203 100644 --- a/java/core/src/main/resources/google/protobuf/java_features.proto +++ b/java/core/src/main/resources/google/protobuf/java_features.proto @@ -83,4 +83,32 @@ message JavaFeatures { edition_defaults = { edition: EDITION_LEGACY, value: "true" }, edition_defaults = { edition: EDITION_2024, value: "false" } ]; + + enum NestInFileClass { + // Invalid default, which should never be used. + NEST_IN_FILE_CLASS_UNKNOWN = 0; + // Do not nest the generated class in the file class. + NO = 1; + // Nest the generated class in the file class. + YES = 2; + // Fall back to the `java_multiple_files` option. Users won't be able to + // set this option. + LEGACY = 3 [feature_support = { + edition_introduced: EDITION_2024 + edition_removed: EDITION_2024 + }]; + } + + optional NestInFileClass nest_in_file_class = 5 [ + retention = RETENTION_RUNTIME, + targets = TARGET_TYPE_FILE, + targets = TARGET_TYPE_MESSAGE, + targets = TARGET_TYPE_ENUM, + targets = TARGET_TYPE_SERVICE, + feature_support = { + edition_introduced: EDITION_2024, + }, + edition_defaults = { edition: EDITION_LEGACY, value: "LEGACY" }, + edition_defaults = { edition: EDITION_2024, value: "NO" } + ]; } diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index f05b62af8979..5a94c5deb24b 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -2310,6 +2310,19 @@ TEST_F(CommandLineInterfaceTest, EditionDefaultsInvalidMaximumUnknown) { ExpectErrorSubstring("unknown edition \"2022\""); } +TEST_F(CommandLineInterfaceTest, JavaMultipleFilesEdition2024Invalid) { + CreateTempFile("foo.proto", + R"schema( + edition = "2024"; + option java_multiple_files = true; + message Bar {} + )schema"); + Run("protocol_compiler --proto_path=$tmpdir " + "foo.proto --test_out=$tmpdir --experimental_editions"); + ExpectErrorSubstring( + "`java_multiple_files` is not supported in editions 2024 and above"); +} + TEST_F(CommandLineInterfaceTest, DirectDependencies_Missing_EmptyList) { CreateTempFile("foo.proto", diff --git a/src/google/protobuf/compiler/java/file.cc b/src/google/protobuf/compiler/java/file.cc index 34aad8667059..5edadf295d7c 100644 --- a/src/google/protobuf/compiler/java/file.cc +++ b/src/google/protobuf/compiler/java/file.cc @@ -349,17 +349,21 @@ void FileGenerator::Generate(io::Printer* printer) { // ----------------------------------------------------------------- - if (!MultipleJavaFiles(file_, immutable_api_)) { - for (int i = 0; i < file_->enum_type_count(); i++) { + for (int i = 0; i < file_->enum_type_count(); i++) { + if (NestedInFileClass(*file_->enum_type(i), immutable_api_)) { generator_factory_->NewEnumGenerator(file_->enum_type(i)) ->Generate(printer); } - for (int i = 0; i < file_->message_type_count(); i++) { + } + for (int i = 0; i < file_->message_type_count(); i++) { + if (NestedInFileClass(*file_->message_type(i), immutable_api_)) { message_generators_[i]->GenerateInterface(printer); message_generators_[i]->Generate(printer); } - if (HasGenericServices(file_, context_->EnforceLite())) { - for (int i = 0; i < file_->service_count(); i++) { + } + if (HasGenericServices(file_, context_->EnforceLite())) { + for (int i = 0; i < file_->service_count(); i++) { + if (NestedInFileClass(*file_->service(i), immutable_api_)) { std::unique_ptr generator( generator_factory_->NewServiceGenerator(file_->service(i))); generator->Generate(printer); @@ -578,38 +582,39 @@ void FileGenerator::GenerateSiblings( const std::string& package_dir, GeneratorContext* context, std::vector* file_list, std::vector* annotation_list) { - if (MultipleJavaFiles(file_, immutable_api_)) { - for (int i = 0; i < file_->enum_type_count(); i++) { - std::unique_ptr generator( - generator_factory_->NewEnumGenerator(file_->enum_type(i))); - GenerateSibling( - package_dir, java_package_, file_->enum_type(i), context, file_list, - options_.annotate_code, annotation_list, "", generator.get(), - options_.opensource_runtime, &EnumGenerator::Generate); - } - for (int i = 0; i < file_->message_type_count(); i++) { - if (immutable_api_) { - GenerateSibling( - package_dir, java_package_, file_->message_type(i), context, - file_list, options_.annotate_code, annotation_list, "OrBuilder", - message_generators_[i].get(), options_.opensource_runtime, - &MessageGenerator::GenerateInterface); - } + for (int i = 0; i < file_->enum_type_count(); i++) { + if (NestedInFileClass(*file_->enum_type(i), immutable_api_)) continue; + std::unique_ptr generator( + generator_factory_->NewEnumGenerator(file_->enum_type(i))); + GenerateSibling( + package_dir, java_package_, file_->enum_type(i), context, file_list, + options_.annotate_code, annotation_list, "", generator.get(), + options_.opensource_runtime, &EnumGenerator::Generate); + } + for (int i = 0; i < file_->message_type_count(); i++) { + if (NestedInFileClass(*file_->message_type(i), immutable_api_)) continue; + if (immutable_api_) { GenerateSibling( package_dir, java_package_, file_->message_type(i), context, - file_list, options_.annotate_code, annotation_list, "", + file_list, options_.annotate_code, annotation_list, "OrBuilder", message_generators_[i].get(), options_.opensource_runtime, - &MessageGenerator::Generate); + &MessageGenerator::GenerateInterface); } - if (HasGenericServices(file_, context_->EnforceLite())) { - for (int i = 0; i < file_->service_count(); i++) { - std::unique_ptr generator( - generator_factory_->NewServiceGenerator(file_->service(i))); - GenerateSibling( - package_dir, java_package_, file_->service(i), context, file_list, - options_.annotate_code, annotation_list, "", generator.get(), - options_.opensource_runtime, &ServiceGenerator::Generate); - } + GenerateSibling( + package_dir, java_package_, file_->message_type(i), context, file_list, + options_.annotate_code, annotation_list, "", + message_generators_[i].get(), options_.opensource_runtime, + &MessageGenerator::Generate); + } + if (HasGenericServices(file_, context_->EnforceLite())) { + for (int i = 0; i < file_->service_count(); i++) { + if (NestedInFileClass(*file_->service(i), immutable_api_)) continue; + std::unique_ptr generator( + generator_factory_->NewServiceGenerator(file_->service(i))); + GenerateSibling( + package_dir, java_package_, file_->service(i), context, file_list, + options_.annotate_code, annotation_list, "", generator.get(), + options_.opensource_runtime, &ServiceGenerator::Generate); } } } diff --git a/src/google/protobuf/compiler/java/full/message.cc b/src/google/protobuf/compiler/java/full/message.cc index b2123501b938..01caaf32fc26 100644 --- a/src/google/protobuf/compiler/java/full/message.cc +++ b/src/google/protobuf/compiler/java/full/message.cc @@ -103,12 +103,12 @@ void ImmutableMessageGenerator::GenerateStaticVariables( if (descriptor_->containing_type() != nullptr) { vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type()); } - if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { + if (NestedInFileClass(*descriptor_, /* immutable = */ true)) { // We can only make these package-private since the classes that use them // are in separate files. - vars["private"] = ""; - } else { vars["private"] = "private "; + } else { + vars["private"] = ""; } if (*bytecode_estimate <= kMaxStaticSize) { vars["final"] = "final "; @@ -179,12 +179,12 @@ void ImmutableMessageGenerator::GenerateFieldAccessorTable( io::Printer* printer, int* bytecode_estimate) { absl::flat_hash_map vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); - if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { + if (NestedInFileClass(*descriptor_, /* immutable = */ true)) { // We can only make these package-private since the classes that use them // are in separate files. - vars["private"] = ""; - } else { vars["private"] = "private "; + } else { + vars["private"] = ""; } if (*bytecode_estimate <= kMaxStaticSize) { vars["final"] = "final "; diff --git a/src/google/protobuf/compiler/java/helpers.cc b/src/google/protobuf/compiler/java/helpers.cc index 8deb2dcec302..f3686fee8bb3 100644 --- a/src/google/protobuf/compiler/java/helpers.cc +++ b/src/google/protobuf/compiler/java/helpers.cc @@ -27,6 +27,8 @@ #include "absl/strings/str_split.h" #include "absl/strings/string_view.h" #include "absl/strings/substitute.h" +#include "google/protobuf/compiler/java/java_features.pb.h" +#include "google/protobuf/compiler/java/generator.h" #include "google/protobuf/compiler/java/name_resolver.h" #include "google/protobuf/compiler/versions.h" #include "google/protobuf/descriptor.pb.h" @@ -918,6 +920,51 @@ const FieldDescriptor* MapValueField(const FieldDescriptor* descriptor) { } +namespace { + +// Get the value of `nest_in_file_class` feature and returns whether the +// generated class should be nested in the generated proto file Java class. +template +inline bool NestInFileClass(const Descriptor& descriptor) { + // TODO b/373884685 - Clean up this check once when we have a way to query + // Java features in the C++ runtime. + // if (JavaGenerator::GetEdition(*descriptor.file()) < EDITION_2024) { + // return !descriptor.file()->options().java_multiple_files(); + // } + auto nest_in_file_class = JavaGenerator::GetResolvedSourceFeatures(descriptor) + .GetExtension(pb::java) + .nest_in_file_class(); + CHECK(nest_in_file_class != pb::JavaFeatures::NEST_IN_FILE_CLASS_UNKNOWN) + << "MMP\n" + << descriptor.DebugString() << "\n" + << descriptor.file()->name(); + if (nest_in_file_class == pb::JavaFeatures::LEGACY) { + return !descriptor.file()->options().java_multiple_files(); + } + ABSL_CHECK(nest_in_file_class != pb::JavaFeatures::LEGACY); + return nest_in_file_class == pb::JavaFeatures::YES; +} + +// Returns whether multiple Java files should be generated for the given +// descriptor, depending on different Protobuf Java API versions. +template +bool MultipleJavaFiles(const Descriptor& descriptor, bool immutable) { + (void)immutable; + return !NestInFileClass(descriptor); +} +} // namespace + +bool NestedInFileClass(const Descriptor& descriptor, bool immutable) { + return !MultipleJavaFiles(descriptor, immutable); +} + +bool NestedInFileClass(const EnumDescriptor& descriptor, bool immutable) { + return !MultipleJavaFiles(descriptor, immutable); +} + +bool NestedInFileClass(const ServiceDescriptor& descriptor, bool immutable) { + return !MultipleJavaFiles(descriptor, immutable); +} } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/helpers.h b/src/google/protobuf/compiler/java/helpers.h index ab21758a7e16..b84315873e29 100644 --- a/src/google/protobuf/compiler/java/helpers.h +++ b/src/google/protobuf/compiler/java/helpers.h @@ -14,10 +14,7 @@ #include #include -#include -#include -#include "absl/container/flat_hash_map.h" #include "absl/strings/string_view.h" #include "google/protobuf/compiler/java/names.h" #include "google/protobuf/compiler/java/options.h" @@ -142,25 +139,30 @@ inline Proto1EnumRepresentation GetProto1EnumRepresentation( return Proto1EnumRepresentation::kInteger; } -// Whether we should generate multiple java files for messages. -inline bool MultipleJavaFiles(const FileDescriptor* descriptor, - bool immutable) { - (void)immutable; - return descriptor->options().java_multiple_files(); -} - +// Returns true if the generated class for the type is nested in the generated +// proto file Java class. +// `immutable` should be set to true if we're generating for the immutable API. +// TODO b/372482046 - Make these functions public so that plugins can use them +// to determine whether to generate multiple files for arbitrary editions +// instead of accessing the `java_multiple_files` file option directly. +bool NestedInFileClass(const Descriptor& descriptor, bool immutable); +bool NestedInFileClass(const EnumDescriptor& descriptor, bool immutable); +bool NestedInFileClass(const ServiceDescriptor& descriptor, bool immutable); // Returns true if `descriptor` will be written to its own .java file. // `immutable` should be set to true if we're generating for the immutable API. +// For nested messages, this always returns false, since their generated Java +// class is always nested in their parent message's Java class i.e. they never +// have their own Java file. template bool IsOwnFile(const Descriptor* descriptor, bool immutable) { return descriptor->containing_type() == nullptr && - MultipleJavaFiles(descriptor->file(), immutable); + !NestedInFileClass(*descriptor, immutable); } template <> inline bool IsOwnFile(const ServiceDescriptor* descriptor, bool immutable) { - return MultipleJavaFiles(descriptor->file(), immutable); + return !NestedInFileClass(*descriptor, immutable); } // If `descriptor` describes an object with its own .java file, diff --git a/src/google/protobuf/compiler/java/java_features.pb.cc b/src/google/protobuf/compiler/java/java_features.pb.cc index 8942b9b296ad..5ac6b9b00c3d 100644 --- a/src/google/protobuf/compiler/java/java_features.pb.cc +++ b/src/google/protobuf/compiler/java/java_features.pb.cc @@ -28,10 +28,11 @@ namespace pb { inline constexpr JavaFeatures::Impl_::Impl_( ::_pbi::ConstantInitialized) noexcept - : _cached_size_{0}, - utf8_validation_{static_cast< ::pb::JavaFeatures_Utf8Validation >(0)}, - legacy_closed_enum_{false}, - use_old_outer_classname_default_{false} {} + : _cached_size_{0}, + utf8_validation_{static_cast<::pb::JavaFeatures_Utf8Validation>(0)}, + legacy_closed_enum_{false}, + use_old_outer_classname_default_{false}, + nest_in_file_class_{static_cast<::pb::JavaFeatures_NestInFileClass>(0)} {} template PROTOBUF_CONSTEXPR JavaFeatures::JavaFeatures(::_pbi::ConstantInitialized) @@ -53,81 +54,114 @@ struct JavaFeaturesDefaultTypeInternal { PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOC_EXPORT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 JavaFeaturesDefaultTypeInternal _JavaFeatures_default_instance_; } // namespace pb -static const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto[1]; +static const ::_pb::EnumDescriptor* + file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto + [2]; static constexpr const ::_pb::ServiceDescriptor** file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto = nullptr; const ::uint32_t - TableStruct_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto::offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE( - protodesc_cold) = { - PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_._has_bits_), - PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _internal_metadata_), - ~0u, // no _extensions_ - ~0u, // no _oneof_case_ - ~0u, // no _weak_field_map_ - ~0u, // no _inlined_string_donated_ - ~0u, // no _split_ - ~0u, // no sizeof(Split) - PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.legacy_closed_enum_), - PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.utf8_validation_), - PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.use_old_outer_classname_default_), - 1, - 0, - 2, + TableStruct_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto:: + offsets[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_._has_bits_), + PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + ~0u, // no _split_ + ~0u, // no sizeof(Split) + PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, + _impl_.legacy_closed_enum_), + PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, _impl_.utf8_validation_), + PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, + _impl_.use_old_outer_classname_default_), + PROTOBUF_FIELD_OFFSET(::pb::JavaFeatures, + _impl_.nest_in_file_class_), + 1, + 0, + 2, + 3, }; -static const ::_pbi::MigrationSchema - schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { - {0, 11, -1, sizeof(::pb::JavaFeatures)}, +static const ::_pbi::MigrationSchema schemas[] ABSL_ATTRIBUTE_SECTION_VARIABLE( + protodesc_cold) = { + {0, 12, -1, sizeof(::pb::JavaFeatures)}, }; static const ::_pb::Message* const file_default_instances[] = { &::pb::_JavaFeatures_default_instance_._instance, }; -const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto[] ABSL_ATTRIBUTE_SECTION_VARIABLE( - protodesc_cold) = { - "\n1google/protobuf/compiler/java/java_fea" - "tures.proto\022\002pb\032 google/protobuf/descrip" - "tor.proto\"\314\005\n\014JavaFeatures\022\376\001\n\022legacy_cl" - "osed_enum\030\001 \001(\010B\341\001\210\001\001\230\001\004\230\001\001\242\001\t\022\004true\030\204\007\242" - "\001\n\022\005false\030\347\007\262\001\273\001\010\350\007\020\350\007\032\262\001The legacy clos" - "ed enum behavior in Java is deprecated a" - "nd is scheduled to be removed in edition" - " 2025. See http://protobuf.dev/programm" - "ing-guides/enum/#java for more informati" - "on.\022\237\002\n\017utf8_validation\030\002 \001(\0162\037.pb.JavaF" - "eatures.Utf8ValidationB\344\001\210\001\001\230\001\004\230\001\001\242\001\014\022\007D" - "EFAULT\030\204\007\262\001\310\001\010\350\007\020\351\007\032\277\001The Java-specific " - "utf8 validation feature is deprecated an" - "d is scheduled to be removed in edition " - "2025. Utf8 validation behavior should u" - "se the global cross-language utf8_valida" - "tion feature.\022Q\n\037use_old_outer_classname" - "_default\030\004 \001(\010B(\210\001\001\230\001\001\242\001\t\022\004true\030\204\007\242\001\n\022\005f" - "alse\030\351\007\262\001\006\010\351\007 \351\007\"F\n\016Utf8Validation\022\033\n\027UT" - "F8_VALIDATION_UNKNOWN\020\000\022\013\n\007DEFAULT\020\001\022\n\n\006" - "VERIFY\020\002:<\n\004java\022\033.google.protobuf.Featu" - "reSet\030\351\007 \001(\0132\020.pb.JavaFeaturesB(\n\023com.go" - "ogle.protobufB\021JavaFeaturesProto" -}; +const char + descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto + [] ABSL_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + "\n1google/protobuf/compiler/java/java_fea" + "tures.proto\022\002pb\032 google/protobuf/descrip" + "tor.proto\"\223\007\n\014JavaFeatures\022\376\001\n\022legacy_cl" + "osed_enum\030\001 " + "\001(" + "\010B\341\001\210\001\001\230\001\004\230\001\001\242\001\t\022" + "\004true\030\204\007\242" + "\001\n\022\005false\030\347\007\262\001\273\001\010\350\007\020" + "\350\007\032\262\001The legacy clos" + "ed enum behavior in Java is deprecated a" + "nd is scheduled to be removed in edition" + " 2025. See http://protobuf.dev/programm" + "ing-guides/enum/#java for more informati" + "on.\022\237\002\n\017utf8_validation\030\002 " + "\001(\0162\037.pb.JavaF" + "eatures." + "Utf8ValidationB\344\001\210\001\001\230\001\004\230\001\001\242" + "\001\014\022\007D" + "EFAULT\030\204\007\262\001\310\001\010\350\007\020\351\007\032\277" + "\001The Java-specific " + "utf8 validation feature is deprecated an" + "d is scheduled to be removed in edition " + "2025. Utf8 validation behavior should u" + "se the global cross-language utf8_valida" + "tion feature.\022Q\n\037use_old_outer_classname" + "_default\030\004 " + "\001(\010B(" + "\210\001\001\230\001\001\242\001\t\022\004true\030\204\007\242\001" + "\n\022\005f" + "alse\030\351\007\262\001\006\010\351\007 " + "\351\007\022k\n\022nest_in_file_class\030\005" + " \001(\0162 .pb.JavaFeatures.NestInFileClassB-" + "\210\001\001\230\001\001\230\001\003\230\001\006\230\001\010\242" + "\001\013\022\006LEGACY\030\204\007\242\001\007\022\002NO\030\351" + "\007\262" + "\001\003\010\351\007\"F\n\016Utf8Validation\022\033\n\027UTF8_" + "VALIDATI" + "ON_" + "UNKNOWN\020\000\022\013\n\007DEFAULT\020\001\022\n\n\006VERIFY\020" + "\002\"X\n" + "\017NestInFileClass\022\036\n\032NEST_IN_FILE_CLASS_U" + "NKNOWN\020\000\022\006\n\002NO\020\001\022\007\n\003YES\020\002" + "\022\024\n\006LEGACY\020\003\032\010\"" + "\006\010\351\007 " + "\351\007:<\n\004java\022\033.google.protobuf.Featur" + "eSet\030\351\007 \001(\0132\020.pb.JavaFeaturesB(\n\023com.goo" + "gle.protobufB\021JavaFeaturesProto"}; static const ::_pbi::DescriptorTable* const descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_deps[1] = { &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto, }; static ::absl::once_flag descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_once; -PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto = { - false, - false, - 912, - descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto, - "google/protobuf/compiler/java/java_features.proto", - &descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_once, - descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_deps, - 1, - 1, - schemas, - file_default_instances, - TableStruct_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto::offsets, - file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto, - file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto, +PROTOBUF_CONSTINIT const ::_pbi::DescriptorTable + descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto = { + false, + false, + 1111, + descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto, + "google/protobuf/compiler/java/java_features.proto", + &descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_once, + descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto_deps, + 1, + 1, + schemas, + file_default_instances, + TableStruct_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto:: + offsets, + file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto, + file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto, }; namespace pb { const ::google::protobuf::EnumDescriptor* JavaFeatures_Utf8Validation_descriptor() { @@ -139,6 +173,21 @@ PROTOBUF_CONSTINIT const uint32_t JavaFeatures_Utf8Validation_internal_data_[] = bool JavaFeatures_Utf8Validation_IsValid(int value) { return 0 <= value && value <= 2; } +const ::google::protobuf::EnumDescriptor* +JavaFeatures_NestInFileClass_descriptor() { + ::google::protobuf::internal::AssignDescriptors( + &descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto); + return file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto + [1]; +} +PROTOBUF_CONSTINIT const uint32_t + JavaFeatures_NestInFileClass_internal_data_[] = { + 262144u, + 0u, +}; +bool JavaFeatures_NestInFileClass_IsValid(int value) { + return 0 <= value && value <= 3; +} // =================================================================== class JavaFeatures::_Internal { @@ -176,12 +225,10 @@ PROTOBUF_NDEBUG_INLINE JavaFeatures::Impl_::Impl_( inline void JavaFeatures::SharedCtor(::_pb::Arena* arena) { new (&_impl_) Impl_(internal_visibility(), arena); - ::memset(reinterpret_cast(&_impl_) + - offsetof(Impl_, utf8_validation_), - 0, - offsetof(Impl_, use_old_outer_classname_default_) - - offsetof(Impl_, utf8_validation_) + - sizeof(Impl_::use_old_outer_classname_default_)); + ::memset( + reinterpret_cast(&_impl_) + offsetof(Impl_, utf8_validation_), 0, + offsetof(Impl_, nest_in_file_class_) - offsetof(Impl_, utf8_validation_) + + sizeof(Impl_::nest_in_file_class_)); } JavaFeatures::~JavaFeatures() { // @@protoc_insertion_point(destructor:pb.JavaFeatures) @@ -235,52 +282,98 @@ const ::google::protobuf::internal::ClassData* JavaFeatures::GetClassData() cons ::google::protobuf::internal::PrefetchToLocalCache(JavaFeatures_class_data_.tc_table); return JavaFeatures_class_data_.base(); } -PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 -const ::_pbi::TcParseTable<2, 3, 1, 0, 2> JavaFeatures::_table_ = { - { - PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_._has_bits_), - 0, // no _extensions_ - 4, 24, // max_field_number, fast_idx_mask - offsetof(decltype(_table_), field_lookup_table), - 4294967284, // skipmap - offsetof(decltype(_table_), field_entries), - 3, // num_field_entries - 1, // num_aux_entries - offsetof(decltype(_table_), aux_entries), - JavaFeatures_class_data_.base(), - nullptr, // post_loop_handler - ::_pbi::TcParser::GenericFallback, // fallback - #ifdef PROTOBUF_PREFETCH_PARSE_TABLE - ::_pbi::TcParser::GetTable<::pb::JavaFeatures>(), // to_prefetch - #endif // PROTOBUF_PREFETCH_PARSE_TABLE - }, {{ - // optional bool use_old_outer_classname_default = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, edition_defaults = { - {::_pbi::TcParser::SingularVarintNoZag1(), - {32, 2, 0, PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.use_old_outer_classname_default_)}}, - // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - {::_pbi::TcParser::SingularVarintNoZag1(), - {8, 1, 0, PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.legacy_closed_enum_)}}, - // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - {::_pbi::TcParser::FastEr0S1, - {16, 0, 2, PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_)}}, - {::_pbi::TcParser::MiniParse, {}}, - }}, {{ - 65535, 65535 - }}, {{ - // optional bool legacy_closed_enum = 1 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.legacy_closed_enum_), _Internal::kHasBitsOffset + 1, 0, - (0 | ::_fl::kFcOptional | ::_fl::kBool)}, - // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { - {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_), _Internal::kHasBitsOffset + 0, 0, - (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)}, - // optional bool use_old_outer_classname_default = 4 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, edition_defaults = { - {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.use_old_outer_classname_default_), _Internal::kHasBitsOffset + 2, 0, - (0 | ::_fl::kFcOptional | ::_fl::kBool)}, - }}, {{ - {0, 3}, - }}, {{ - }}, -}; +PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const ::_pbi::TcParseTable< + 3, 4, 2, 0, 2> + JavaFeatures::_table_ = { + { + PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_._has_bits_), + 0, // no _extensions_ + 5, 56, // max_field_number, fast_idx_mask + offsetof(decltype(_table_), field_lookup_table), + 4294967268, // skipmap + offsetof(decltype(_table_), field_entries), + 4, // num_field_entries + 2, // num_aux_entries + offsetof(decltype(_table_), aux_entries), + JavaFeatures_class_data_.base(), + nullptr, // post_loop_handler + ::_pbi::TcParser::GenericFallback, // fallback +#ifdef PROTOBUF_PREFETCH_PARSE_TABLE + ::_pbi::TcParser::GetTable<::pb::JavaFeatures>(), // to_prefetch +#endif // PROTOBUF_PREFETCH_PARSE_TABLE + }, + {{ + {::_pbi::TcParser::MiniParse, {}}, + // optional bool legacy_closed_enum = 1 [retention = + // RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = + // TARGET_TYPE_FILE, edition_defaults = { + {::_pbi::TcParser::SingularVarintNoZag1< + bool, offsetof(JavaFeatures, _impl_.legacy_closed_enum_), 1>(), + {8, 1, 0, + PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.legacy_closed_enum_)}}, + // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 + // [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, + // targets = TARGET_TYPE_FILE, edition_defaults = { + {::_pbi::TcParser::FastEr0S1, + {16, 0, 2, + PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_)}}, + {::_pbi::TcParser::MiniParse, {}}, + // optional bool use_old_outer_classname_default = 4 [retention = + // RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, edition_defaults = + // { + {::_pbi::TcParser::SingularVarintNoZag1< + bool, + offsetof(JavaFeatures, + _impl_.use_old_outer_classname_default_), + 2>(), + {32, 2, 0, + PROTOBUF_FIELD_OFFSET(JavaFeatures, + _impl_.use_old_outer_classname_default_)}}, + // optional .pb.JavaFeatures.NestInFileClass nest_in_file_class = 5 + // [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, + // targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, + // targets = TARGET_TYPE_SERVICE, edition_defaults = { + {::_pbi::TcParser::FastEr0S1, + {40, 3, 3, + PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.nest_in_file_class_)}}, + {::_pbi::TcParser::MiniParse, {}}, + {::_pbi::TcParser::MiniParse, {}}, + }}, + {{65535, 65535}}, + {{ + // optional bool legacy_closed_enum = 1 [retention = + // RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = + // TARGET_TYPE_FILE, edition_defaults = { + {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.legacy_closed_enum_), + _Internal::kHasBitsOffset + 1, 0, + (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 + // [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, + // targets = TARGET_TYPE_FILE, edition_defaults = { + {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_), + _Internal::kHasBitsOffset + 0, 0, + (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)}, + // optional bool use_old_outer_classname_default = 4 [retention = + // RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, edition_defaults = + // { + {PROTOBUF_FIELD_OFFSET(JavaFeatures, + _impl_.use_old_outer_classname_default_), + _Internal::kHasBitsOffset + 2, 0, + (0 | ::_fl::kFcOptional | ::_fl::kBool)}, + // optional .pb.JavaFeatures.NestInFileClass nest_in_file_class = 5 + // [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, + // targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, + // targets = TARGET_TYPE_SERVICE, edition_defaults = { + {PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.nest_in_file_class_), + _Internal::kHasBitsOffset + 3, 1, + (0 | ::_fl::kFcOptional | ::_fl::kEnumRange)}, + }}, + {{ + {0, 3}, + {0, 4}, + }}, + {{}}, + }; PROTOBUF_NOINLINE void JavaFeatures::Clear() { // @@protoc_insertion_point(message_clear_start:pb.JavaFeatures) @@ -290,10 +383,12 @@ PROTOBUF_NOINLINE void JavaFeatures::Clear() { (void) cached_has_bits; cached_has_bits = _impl_._has_bits_[0]; - if (cached_has_bits & 0x00000007u) { - ::memset(&_impl_.utf8_validation_, 0, static_cast<::size_t>( - reinterpret_cast(&_impl_.use_old_outer_classname_default_) - - reinterpret_cast(&_impl_.utf8_validation_)) + sizeof(_impl_.use_old_outer_classname_default_)); + if (cached_has_bits & 0x0000000fu) { + ::memset(&_impl_.utf8_validation_, 0, + static_cast<::size_t>( + reinterpret_cast(&_impl_.nest_in_file_class_) - + reinterpret_cast(&_impl_.utf8_validation_)) + + sizeof(_impl_.nest_in_file_class_)); } _impl_._has_bits_.Clear(); _internal_metadata_.Clear<::google::protobuf::UnknownFieldSet>(); @@ -336,6 +431,16 @@ PROTOBUF_NOINLINE void JavaFeatures::Clear() { 4, this_._internal_use_old_outer_classname_default(), target); } + // optional .pb.JavaFeatures.NestInFileClass nest_in_file_class = 5 + // [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, targets + // = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, targets = + // TARGET_TYPE_SERVICE, edition_defaults = { + if (cached_has_bits & 0x00000008u) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteEnumToArray( + 5, this_._internal_nest_in_file_class(), target); + } + if (ABSL_PREDICT_FALSE(this_._internal_metadata_.have_unknown_fields())) { target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( @@ -361,7 +466,7 @@ PROTOBUF_NOINLINE void JavaFeatures::Clear() { ::_pbi::Prefetch5LinesFrom7Lines(&this_); cached_has_bits = this_._impl_._has_bits_[0]; - if (cached_has_bits & 0x00000007u) { + if (cached_has_bits & 0x0000000fu) { // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { if (cached_has_bits & 0x00000001u) { total_size += 1 + @@ -375,6 +480,14 @@ PROTOBUF_NOINLINE void JavaFeatures::Clear() { if (cached_has_bits & 0x00000004u) { total_size += 2; } + // optional .pb.JavaFeatures.NestInFileClass nest_in_file_class = 5 + // [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, + // targets = TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, + // targets = TARGET_TYPE_SERVICE, edition_defaults = { + if (cached_has_bits & 0x00000008u) { + total_size += 1 + ::_pbi::WireFormatLite::EnumSize( + this_._internal_nest_in_file_class()); + } } return this_.MaybeComputeUnknownFieldsSize(total_size, &this_._impl_._cached_size_); @@ -389,7 +502,7 @@ void JavaFeatures::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::go (void) cached_has_bits; cached_has_bits = from._impl_._has_bits_[0]; - if (cached_has_bits & 0x00000007u) { + if (cached_has_bits & 0x0000000fu) { if (cached_has_bits & 0x00000001u) { _this->_impl_.utf8_validation_ = from._impl_.utf8_validation_; } @@ -399,6 +512,9 @@ void JavaFeatures::MergeImpl(::google::protobuf::MessageLite& to_msg, const ::go if (cached_has_bits & 0x00000004u) { _this->_impl_.use_old_outer_classname_default_ = from._impl_.use_old_outer_classname_default_; } + if (cached_has_bits & 0x00000008u) { + _this->_impl_.nest_in_file_class_ = from._impl_.nest_in_file_class_; + } } _this->_impl_._has_bits_[0] |= cached_has_bits; _this->_internal_metadata_.MergeFrom<::google::protobuf::UnknownFieldSet>(from._internal_metadata_); @@ -417,11 +533,11 @@ void JavaFeatures::InternalSwap(JavaFeatures* PROTOBUF_RESTRICT other) { _internal_metadata_.InternalSwap(&other->_internal_metadata_); swap(_impl_._has_bits_[0], other->_impl_._has_bits_[0]); ::google::protobuf::internal::memswap< - PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.use_old_outer_classname_default_) - + sizeof(JavaFeatures::_impl_.use_old_outer_classname_default_) - - PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_)>( - reinterpret_cast(&_impl_.utf8_validation_), - reinterpret_cast(&other->_impl_.utf8_validation_)); + PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.nest_in_file_class_) + + sizeof(JavaFeatures::_impl_.nest_in_file_class_) - + PROTOBUF_FIELD_OFFSET(JavaFeatures, _impl_.utf8_validation_)>( + reinterpret_cast(&_impl_.utf8_validation_), + reinterpret_cast(&other->_impl_.utf8_validation_)); } ::google::protobuf::Metadata JavaFeatures::GetMetadata() const { diff --git a/src/google/protobuf/compiler/java/java_features.pb.h b/src/google/protobuf/compiler/java/java_features.pb.h index 50ea5e79dd6e..08d72813216b 100644 --- a/src/google/protobuf/compiler/java/java_features.pb.h +++ b/src/google/protobuf/compiler/java/java_features.pb.h @@ -56,6 +56,10 @@ PROTOC_EXPORT extern const ::google::protobuf::internal::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fjava_2fjava_5ffeatures_2eproto; } // extern "C" namespace pb { +enum JavaFeatures_NestInFileClass : int; +PROTOC_EXPORT bool JavaFeatures_NestInFileClass_IsValid(int value); +PROTOC_EXPORT extern const uint32_t + JavaFeatures_NestInFileClass_internal_data_[]; enum JavaFeatures_Utf8Validation : int; PROTOC_EXPORT bool JavaFeatures_Utf8Validation_IsValid(int value); PROTOC_EXPORT extern const uint32_t JavaFeatures_Utf8Validation_internal_data_[]; @@ -67,6 +71,9 @@ PROTOC_EXPORT extern const ::google::protobuf::internal::ClassDataFull JavaFeatu namespace google { namespace protobuf { template <> +internal::EnumTraitsT<::pb::JavaFeatures_NestInFileClass_internal_data_> + internal::EnumTraitsImpl::value<::pb::JavaFeatures_NestInFileClass>; +template <> internal::EnumTraitsT<::pb::JavaFeatures_Utf8Validation_internal_data_> internal::EnumTraitsImpl::value<::pb::JavaFeatures_Utf8Validation>; } // namespace protobuf @@ -105,6 +112,46 @@ inline bool JavaFeatures_Utf8Validation_Parse(absl::string_view name, JavaFeatur return ::google::protobuf::internal::ParseNamedEnum( JavaFeatures_Utf8Validation_descriptor(), name, value); } +enum JavaFeatures_NestInFileClass : int { + JavaFeatures_NestInFileClass_NEST_IN_FILE_CLASS_UNKNOWN = 0, + JavaFeatures_NestInFileClass_NO = 1, + JavaFeatures_NestInFileClass_YES = 2, + JavaFeatures_NestInFileClass_LEGACY = 3, +}; + +PROTOC_EXPORT bool JavaFeatures_NestInFileClass_IsValid(int value); +PROTOC_EXPORT extern const uint32_t + JavaFeatures_NestInFileClass_internal_data_[]; +inline constexpr JavaFeatures_NestInFileClass + JavaFeatures_NestInFileClass_NestInFileClass_MIN = + static_cast(0); +inline constexpr JavaFeatures_NestInFileClass + JavaFeatures_NestInFileClass_NestInFileClass_MAX = + static_cast(3); +inline constexpr int JavaFeatures_NestInFileClass_NestInFileClass_ARRAYSIZE = + 3 + 1; +PROTOC_EXPORT const ::google::protobuf::EnumDescriptor* +JavaFeatures_NestInFileClass_descriptor(); +template +const std::string& JavaFeatures_NestInFileClass_Name(T value) { + static_assert(std::is_same::value || + std::is_integral::value, + "Incorrect type passed to NestInFileClass_Name()."); + return JavaFeatures_NestInFileClass_Name( + static_cast(value)); +} +template <> +inline const std::string& JavaFeatures_NestInFileClass_Name( + JavaFeatures_NestInFileClass value) { + return ::google::protobuf::internal::NameOfDenseEnum< + JavaFeatures_NestInFileClass_descriptor, 0, 3>(static_cast(value)); +} +inline bool JavaFeatures_NestInFileClass_Parse( + absl::string_view name, JavaFeatures_NestInFileClass* value) { + return ::google::protobuf::internal::ParseNamedEnum< + JavaFeatures_NestInFileClass>(JavaFeatures_NestInFileClass_descriptor(), + name, value); +} // =================================================================== @@ -273,12 +320,40 @@ class PROTOC_EXPORT JavaFeatures final static inline bool Utf8Validation_Parse(absl::string_view name, Utf8Validation* value) { return JavaFeatures_Utf8Validation_Parse(name, value); } + using NestInFileClass = JavaFeatures_NestInFileClass; + static constexpr NestInFileClass NEST_IN_FILE_CLASS_UNKNOWN = + JavaFeatures_NestInFileClass_NEST_IN_FILE_CLASS_UNKNOWN; + static constexpr NestInFileClass NO = JavaFeatures_NestInFileClass_NO; + static constexpr NestInFileClass YES = JavaFeatures_NestInFileClass_YES; + static constexpr NestInFileClass LEGACY = JavaFeatures_NestInFileClass_LEGACY; + static inline bool NestInFileClass_IsValid(int value) { + return JavaFeatures_NestInFileClass_IsValid(value); + } + static constexpr NestInFileClass NestInFileClass_MIN = + JavaFeatures_NestInFileClass_NestInFileClass_MIN; + static constexpr NestInFileClass NestInFileClass_MAX = + JavaFeatures_NestInFileClass_NestInFileClass_MAX; + static constexpr int NestInFileClass_ARRAYSIZE = + JavaFeatures_NestInFileClass_NestInFileClass_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + NestInFileClass_descriptor() { + return JavaFeatures_NestInFileClass_descriptor(); + } + template + static inline const std::string& NestInFileClass_Name(T value) { + return JavaFeatures_NestInFileClass_Name(value); + } + static inline bool NestInFileClass_Parse(absl::string_view name, + NestInFileClass* value) { + return JavaFeatures_NestInFileClass_Parse(name, value); + } // accessors ------------------------------------------------------- enum : int { kUtf8ValidationFieldNumber = 2, kLegacyClosedEnumFieldNumber = 1, kUseOldOuterClassnameDefaultFieldNumber = 4, + kNestInFileClassFieldNumber = 5, }; // optional .pb.JavaFeatures.Utf8Validation utf8_validation = 2 [retention = RETENTION_RUNTIME, targets = TARGET_TYPE_FIELD, targets = TARGET_TYPE_FILE, edition_defaults = { bool has_utf8_validation() const; @@ -312,14 +387,27 @@ class PROTOC_EXPORT JavaFeatures final bool _internal_use_old_outer_classname_default() const; void _internal_set_use_old_outer_classname_default(bool value); - public: + public: + // optional .pb.JavaFeatures.NestInFileClass nest_in_file_class = 5 [retention + // = RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, targets = + // TARGET_TYPE_MESSAGE, targets = TARGET_TYPE_ENUM, targets = + // TARGET_TYPE_SERVICE, edition_defaults = { + bool has_nest_in_file_class() const; + void clear_nest_in_file_class(); + ::pb::JavaFeatures_NestInFileClass nest_in_file_class() const; + void set_nest_in_file_class(::pb::JavaFeatures_NestInFileClass value); + + private: + ::pb::JavaFeatures_NestInFileClass _internal_nest_in_file_class() const; + void _internal_set_nest_in_file_class( + ::pb::JavaFeatures_NestInFileClass value); + + public: // @@protoc_insertion_point(class_scope:pb.JavaFeatures) private: class _Internal; friend class ::google::protobuf::internal::TcParser; - static const ::google::protobuf::internal::TcParseTable< - 2, 3, 1, - 0, 2> + static const ::google::protobuf::internal::TcParseTable<3, 4, 2, 0, 2> _table_; friend class ::google::protobuf::MessageLite; @@ -341,6 +429,7 @@ class PROTOC_EXPORT JavaFeatures final int utf8_validation_; bool legacy_closed_enum_; bool use_old_outer_classname_default_; + int nest_in_file_class_; PROTOBUF_TSAN_DECLARE_MEMBER }; union { Impl_ _impl_; }; @@ -456,6 +545,43 @@ inline void JavaFeatures::_internal_set_use_old_outer_classname_default(bool val _impl_.use_old_outer_classname_default_ = value; } +// optional .pb.JavaFeatures.NestInFileClass nest_in_file_class = 5 [retention = +// RETENTION_RUNTIME, targets = TARGET_TYPE_FILE, targets = TARGET_TYPE_MESSAGE, +// targets = TARGET_TYPE_ENUM, targets = TARGET_TYPE_SERVICE, edition_defaults = +// { +inline bool JavaFeatures::has_nest_in_file_class() const { + bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0; + return value; +} +inline void JavaFeatures::clear_nest_in_file_class() { + ::google::protobuf::internal::TSanWrite(&_impl_); + _impl_.nest_in_file_class_ = 0; + _impl_._has_bits_[0] &= ~0x00000008u; +} +inline ::pb::JavaFeatures_NestInFileClass JavaFeatures::nest_in_file_class() + const { + // @@protoc_insertion_point(field_get:pb.JavaFeatures.nest_in_file_class) + return _internal_nest_in_file_class(); +} +inline void JavaFeatures::set_nest_in_file_class( + ::pb::JavaFeatures_NestInFileClass value) { + _internal_set_nest_in_file_class(value); + _impl_._has_bits_[0] |= 0x00000008u; + // @@protoc_insertion_point(field_set:pb.JavaFeatures.nest_in_file_class) +} +inline ::pb::JavaFeatures_NestInFileClass +JavaFeatures::_internal_nest_in_file_class() const { + ::google::protobuf::internal::TSanRead(&_impl_); + return static_cast<::pb::JavaFeatures_NestInFileClass>( + _impl_.nest_in_file_class_); +} +inline void JavaFeatures::_internal_set_nest_in_file_class( + ::pb::JavaFeatures_NestInFileClass value) { + ::google::protobuf::internal::TSanWrite(&_impl_); + assert(::pb::JavaFeatures_NestInFileClass_IsValid(value)); + _impl_.nest_in_file_class_ = value; +} + #ifdef __GNUC__ #pragma GCC diagnostic pop #endif // __GNUC__ @@ -473,6 +599,13 @@ template <> inline const EnumDescriptor* GetEnumDescriptor<::pb::JavaFeatures_Utf8Validation>() { return ::pb::JavaFeatures_Utf8Validation_descriptor(); } +template <> +struct is_proto_enum<::pb::JavaFeatures_NestInFileClass> : std::true_type {}; +template <> +inline const EnumDescriptor* +GetEnumDescriptor<::pb::JavaFeatures_NestInFileClass>() { + return ::pb::JavaFeatures_NestInFileClass_descriptor(); +} } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/compiler/java/name_resolver.cc b/src/google/protobuf/compiler/java/name_resolver.cc index 869e69a320d2..e78c2646144f 100644 --- a/src/google/protobuf/compiler/java/name_resolver.cc +++ b/src/google/protobuf/compiler/java/name_resolver.cc @@ -240,19 +240,19 @@ std::string ClassNameResolver::GetClassName(const FileDescriptor* descriptor, // or outer class name. std::string ClassNameResolver::GetClassFullName( absl::string_view name_without_package, const FileDescriptor* file, - bool immutable, bool is_own_file) { - return GetClassFullName(name_without_package, file, immutable, is_own_file, - false); + bool immutable, bool nest_in_file_class) { + return GetClassFullName(name_without_package, file, immutable, + nest_in_file_class, false); } std::string ClassNameResolver::GetClassFullName( absl::string_view name_without_package, const FileDescriptor* file, - bool immutable, bool is_own_file, bool kotlin) { + bool immutable, bool nest_in_file_class, bool kotlin) { std::string result; - if (is_own_file) { - result = FileJavaPackage(file, immutable, options_); - } else { + if (nest_in_file_class) { result = GetClassName(file, immutable, kotlin); + } else { + result = FileJavaPackage(file, immutable, options_); } if (!result.empty()) { absl::StrAppend(&result, "."); @@ -269,9 +269,9 @@ std::string ClassNameResolver::GetClassName(const Descriptor* descriptor, std::string ClassNameResolver::GetClassName(const Descriptor* descriptor, bool immutable, bool kotlin) { - return GetClassFullName( - ClassNameWithoutPackage(descriptor, immutable), descriptor->file(), - immutable, MultipleJavaFiles(descriptor->file(), immutable), kotlin); + return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), + descriptor->file(), immutable, + NestedInFileClass(*descriptor, immutable), kotlin); } std::string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor, @@ -281,9 +281,9 @@ std::string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor, std::string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor, bool immutable, bool kotlin) { - return GetClassFullName( - ClassNameWithoutPackage(descriptor, immutable), descriptor->file(), - immutable, MultipleJavaFiles(descriptor->file(), immutable), kotlin); + return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), + descriptor->file(), immutable, + NestedInFileClass(*descriptor, immutable), kotlin); } std::string ClassNameResolver::GetClassName(const ServiceDescriptor* descriptor, @@ -295,26 +295,30 @@ std::string ClassNameResolver::GetClassName(const ServiceDescriptor* descriptor, bool immutable, bool kotlin) { return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), descriptor->file(), immutable, - IsOwnFile(descriptor, immutable), kotlin); + !IsOwnFile(descriptor, immutable), kotlin); } -// Get the Java Class style full name of a message. +template std::string ClassNameResolver::GetJavaClassFullName( - absl::string_view name_without_package, const FileDescriptor* file, + absl::string_view name_without_package, const Descriptor& descriptor, bool immutable) { - return GetJavaClassFullName(name_without_package, file, immutable, false); + return GetJavaClassFullName(name_without_package, descriptor, immutable, + /*kotlin =*/false); } +// Get the Java Class style full name of a type. +template std::string ClassNameResolver::GetJavaClassFullName( - absl::string_view name_without_package, const FileDescriptor* file, + absl::string_view name_without_package, const Descriptor& descriptor, bool immutable, bool kotlin) { std::string result; - if (MultipleJavaFiles(file, immutable)) { - result = FileJavaPackage(file, immutable, options_); - if (!result.empty()) result += '.'; - } else { + auto file = descriptor.file(); + if (NestedInFileClass(descriptor, immutable)) { result = GetClassName(file, immutable, kotlin); if (!result.empty()) result += '$'; + } else { + result = FileJavaPackage(file, immutable, options_); + if (!result.empty()) result += '.'; } result += absl::StrReplaceAll(name_without_package, {{".", "$"}}); return result; @@ -341,32 +345,35 @@ std::string ClassNameResolver::GetKotlinFactoryName( std::string ClassNameResolver::GetJavaImmutableClassName( const Descriptor* descriptor) { return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, true), - descriptor->file(), true); + *descriptor, true); } std::string ClassNameResolver::GetJavaImmutableClassName( const EnumDescriptor* descriptor) { return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, true), - descriptor->file(), true); + *descriptor, true); } std::string ClassNameResolver::GetJavaImmutableClassName( const ServiceDescriptor* descriptor) { return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, true), - descriptor->file(), true); + *descriptor, true); } std::string ClassNameResolver::GetKotlinExtensionsClassName( const Descriptor* descriptor) { return GetClassFullName(ClassNameWithoutPackageKotlin(descriptor), - descriptor->file(), true, true, true); + descriptor->file(), /*immutable=*/true, + /*nest_in_file_class=*/false, + /*kotlin=*/true); } std::string ClassNameResolver::GetKotlinExtensionsClassNameEscaped( const Descriptor* descriptor) { std::string name_without_package = ClassNameWithoutPackageKotlin(descriptor); std::string full_name = GetClassFullName( - name_without_package, descriptor->file(), true, true, true); + name_without_package, descriptor->file(), /*immutable=*/true, + /*nest_in_file_class=*/false, /*kotlin=*/true); std::string name_without_package_suffix = absl::StrCat(".", name_without_package, "Kt"); size_t package_end = full_name.rfind(name_without_package_suffix); @@ -380,19 +387,19 @@ std::string ClassNameResolver::GetKotlinExtensionsClassNameEscaped( std::string ClassNameResolver::GetJavaMutableClassName( const Descriptor* descriptor) { return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, false), - descriptor->file(), false); + *descriptor, false); } std::string ClassNameResolver::GetJavaMutableClassName( const EnumDescriptor* descriptor) { return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, false), - descriptor->file(), false); + *descriptor, false); } std::string ClassNameResolver::GetJavaMutableClassName( const ServiceDescriptor* descriptor) { return GetJavaClassFullName(ClassNameWithoutPackage(descriptor, false), - descriptor->file(), false); + *descriptor, false); } std::string ClassNameResolver::GetDowngradedFileClassName( diff --git a/src/google/protobuf/compiler/java/name_resolver.h b/src/google/protobuf/compiler/java/name_resolver.h index 85b80177596a..3a76243e07a0 100644 --- a/src/google/protobuf/compiler/java/name_resolver.h +++ b/src/google/protobuf/compiler/java/name_resolver.h @@ -114,19 +114,22 @@ class PROTOC_EXPORT ClassNameResolver { // or outer class name. std::string GetClassFullName(absl::string_view name_without_package, const FileDescriptor* file, bool immutable, - bool is_own_file); + bool nest_in_file_class); std::string GetClassFullName(absl::string_view name_without_package, const FileDescriptor* file, bool immutable, - bool is_own_file, bool kotlin); + bool nest_in_file_class, bool kotlin); Options options_; private: // Get the Java Class style full name of a message. + template std::string GetJavaClassFullName(absl::string_view name_without_package, - const FileDescriptor* file, bool immutable); + const Descriptor& descriptor, + bool immutable); + template std::string GetJavaClassFullName(absl::string_view name_without_package, - const FileDescriptor* file, bool immutable, + const Descriptor& descriptor, bool immutable, bool kotlin); // Caches the result to provide better performance. absl::flat_hash_map diff --git a/src/google/protobuf/compiler/java/name_resolver_test.cc b/src/google/protobuf/compiler/java/name_resolver_test.cc index 201390b1bd5f..3873bfaed152 100644 --- a/src/google/protobuf/compiler/java/name_resolver_test.cc +++ b/src/google/protobuf/compiler/java/name_resolver_test.cc @@ -54,10 +54,13 @@ class NameResolverTest : public testing::Test { BuildFileAndPopulatePool( "google/protobuf/descriptor.proto", google::protobuf::DescriptorProto::descriptor()->file()->DebugString()); + BuildFileAndPopulatePool( + "third_party/java/protobuf/java_features.proto", + pb::JavaFeatures::descriptor()->file()->DebugString()); } - void BuildFileAndPopulatePool(absl::string_view filename, - absl::string_view contents) { + const FileDescriptor* BuildFileAndPopulatePool(absl::string_view filename, + absl::string_view contents) { io::ArrayInputStream input_stream(contents.data(), contents.size()); SimpleErrorCollector error_collector; io::Tokenizer tokenizer(&input_stream, &error_collector); @@ -69,15 +72,15 @@ class NameResolverTest : public testing::Test { << contents; ABSL_CHECK_EQ("", error_collector.last_error()); proto.set_name(filename); - pool_.BuildFile(proto); + return pool_.BuildFile(proto); } DescriptorPool pool_; }; TEST_F(NameResolverTest, FileImmutableClassNameEdition2024) { - BuildFileAndPopulatePool("foo.proto", - R"schema( + auto file = BuildFileAndPopulatePool("foo.proto", + R"schema( edition = "2024"; package protobuf_unittest; @@ -93,14 +96,13 @@ TEST_F(NameResolverTest, FileImmutableClassNameEdition2024) { )schema"); ClassNameResolver resolver; - auto file = pool_.FindFileByName("foo.proto"); EXPECT_EQ(resolver.GetFileDefaultImmutableClassName(file), "FooProto"); EXPECT_EQ(resolver.GetFileImmutableClassName(file), "FooProto"); } TEST_F(NameResolverTest, FileImmutableClassNameDefaultOverriddenEdition2024) { - BuildFileAndPopulatePool("foo.proto", - R"schema( + auto file = BuildFileAndPopulatePool("foo.proto", + R"schema( edition = "2024"; package protobuf_unittest; @@ -113,14 +115,13 @@ TEST_F(NameResolverTest, FileImmutableClassNameDefaultOverriddenEdition2024) { )schema"); ClassNameResolver resolver; - auto file = pool_.FindFileByName("foo.proto"); EXPECT_EQ(resolver.GetFileDefaultImmutableClassName(file), "FooProto"); EXPECT_EQ(resolver.GetFileImmutableClassName(file), "BarBuz"); } TEST_F(NameResolverTest, FileImmutableClassNameEdition2023) { - BuildFileAndPopulatePool("conflicting_file_class_name.proto", - R"schema( + auto file = BuildFileAndPopulatePool("conflicting_file_class_name.proto", + R"schema( edition = "2023"; package protobuf_unittest; @@ -131,16 +132,15 @@ TEST_F(NameResolverTest, FileImmutableClassNameEdition2023) { )schema"); ClassNameResolver resolver; - auto file = pool_.FindFileByName("conflicting_file_class_name.proto"); EXPECT_EQ(resolver.GetFileDefaultImmutableClassName(file), "ConflictingFileClassName"); EXPECT_EQ(resolver.GetFileImmutableClassName(file), "ConflictingFileClassNameOuterClass"); } -TEST_F(NameResolverTest, MultipleFilesServiceEdition2023) { - BuildFileAndPopulatePool("foo.proto", - R"schema( +TEST_F(NameResolverTest, JavaMultipleFilesService) { + const FileDescriptor* file = BuildFileAndPopulatePool("foo.proto", + R"schema( edition = "2023"; option java_generic_services = true; @@ -154,8 +154,7 @@ TEST_F(NameResolverTest, MultipleFilesServiceEdition2023) { } )schema"); - auto service_descriptor = - pool_.FindServiceByName("protobuf_unittest.FooService"); + auto service_descriptor = file->FindServiceByName("FooService"); ClassNameResolver resolver; EXPECT_EQ(resolver.GetClassName(service_descriptor, /* immutable = */ true), PACKAGE_PREFIX "protobuf_unittest.FooService"); @@ -163,9 +162,9 @@ TEST_F(NameResolverTest, MultipleFilesServiceEdition2023) { PACKAGE_PREFIX "protobuf_unittest.FooService"); } -TEST_F(NameResolverTest, SingleFileServiceEdition2023) { - BuildFileAndPopulatePool("foo.proto", - R"schema( +TEST_F(NameResolverTest, JavaMultipleFilesFalseService) { + auto file = BuildFileAndPopulatePool("foo.proto", + R"schema( edition = "2023"; option java_generic_services = true; @@ -178,18 +177,49 @@ TEST_F(NameResolverTest, SingleFileServiceEdition2023) { } )schema"); - auto service_descriptor = - pool_.FindServiceByName("protobuf_unittest.FooService"); + auto service_descriptor = file->FindServiceByName("FooService"); ClassNameResolver resolver; EXPECT_EQ(resolver.GetClassName(service_descriptor, /* immutable = */ true), PACKAGE_PREFIX "protobuf_unittest.Foo.FooService"); EXPECT_EQ(resolver.GetJavaImmutableClassName(service_descriptor), PACKAGE_PREFIX "protobuf_unittest.Foo$FooService"); } +TEST_F(NameResolverTest, NestInFileClassService) { + auto file = BuildFileAndPopulatePool("foo.proto", + R"schema( + edition = "2024"; + import "third_party/java/protobuf/java_features.proto"; + package protobuf_unittest; + option java_generic_services = true; + message Dummy {} + service NestedInFileClassService { + option features.(pb.java).nest_in_file_class = YES; + rpc Method(Dummy) returns (Dummy) {} + } + service UnnestedService { + rpc Method(Dummy) returns (Dummy) {} + } + )schema"); + ClassNameResolver resolver; + auto nested_service = file->FindServiceByName("NestedInFileClassService"); + auto unnested_service = file->FindServiceByName("UnnestedService"); + + EXPECT_EQ(resolver.GetClassName(unnested_service, + /* immutable = */ true), + PACKAGE_PREFIX "protobuf_unittest.UnnestedService"); + EXPECT_EQ(resolver.GetClassName(nested_service, + /* immutable = */ true), + PACKAGE_PREFIX + "protobuf_unittest.FooProto.NestedInFileClassService"); + EXPECT_EQ(resolver.GetJavaImmutableClassName(unnested_service), + PACKAGE_PREFIX "protobuf_unittest.UnnestedService"); + EXPECT_EQ(resolver.GetJavaImmutableClassName(nested_service), PACKAGE_PREFIX + "protobuf_unittest.FooProto$NestedInFileClassService"); +} -TEST_F(NameResolverTest, MultipleFilesMessageEdition2023) { - BuildFileAndPopulatePool("foo.proto", - R"schema( +TEST_F(NameResolverTest, JavaMultipleFilesMessage) { + auto file = BuildFileAndPopulatePool("foo.proto", + R"schema( edition = "2023"; option java_multiple_files = true; @@ -199,8 +229,7 @@ TEST_F(NameResolverTest, MultipleFilesMessageEdition2023) { message FooMessage {} )schema"); - auto message_descriptor = - pool_.FindMessageTypeByName("protobuf_unittest.FooMessage"); + auto message_descriptor = file->FindMessageTypeByName("FooMessage"); ClassNameResolver resolver; EXPECT_EQ(resolver.GetClassName(message_descriptor, /* immutable = */ true), @@ -209,9 +238,9 @@ TEST_F(NameResolverTest, MultipleFilesMessageEdition2023) { PACKAGE_PREFIX "protobuf_unittest.FooMessage"); } -TEST_F(NameResolverTest, SingleFileMessageEdition2023) { - BuildFileAndPopulatePool("foo.proto", - R"schema( +TEST_F(NameResolverTest, JavaMultipleFilesFalseMessage) { + auto file = BuildFileAndPopulatePool("foo.proto", + R"schema( edition = "2023"; package protobuf_unittest; @@ -219,8 +248,7 @@ TEST_F(NameResolverTest, SingleFileMessageEdition2023) { message FooMessage {} )schema"); - auto message_descriptor = - pool_.FindMessageTypeByName("protobuf_unittest.FooMessage"); + auto message_descriptor = file->FindMessageTypeByName("FooMessage"); ClassNameResolver resolver; EXPECT_EQ(resolver.GetClassName(message_descriptor, /* immutable = */ true), @@ -229,9 +257,41 @@ TEST_F(NameResolverTest, SingleFileMessageEdition2023) { PACKAGE_PREFIX "protobuf_unittest.Foo$FooMessage"); } -TEST_F(NameResolverTest, MultipleFilesEnumEdition2023) { - BuildFileAndPopulatePool("foo.proto", - R"schema( +TEST_F(NameResolverTest, NestInFileClassMessage) { + auto file = BuildFileAndPopulatePool("foo.proto", + R"schema( + edition = "2024"; + import "third_party/java/protobuf/java_features.proto"; + package protobuf_unittest; + message NestedInFileClassMessage { + option features.(pb.java).nest_in_file_class = YES; + int32 unused = 1; + } + message UnnestedMessage { + int32 unused = 1; + } + )schema"); + + ClassNameResolver resolver; + auto nested_message = file->FindMessageTypeByName("NestedInFileClassMessage"); + auto unnested_message = file->FindMessageTypeByName("UnnestedMessage"); + + EXPECT_EQ(resolver.GetClassName(unnested_message, + /* immutable = */ true), + PACKAGE_PREFIX "protobuf_unittest.UnnestedMessage"); + EXPECT_EQ(resolver.GetClassName(nested_message, + /* immutable = */ true), + PACKAGE_PREFIX + "protobuf_unittest.FooProto.NestedInFileClassMessage"); + EXPECT_EQ(resolver.GetJavaImmutableClassName(unnested_message), + PACKAGE_PREFIX "protobuf_unittest.UnnestedMessage"); + EXPECT_EQ(resolver.GetJavaImmutableClassName(nested_message), PACKAGE_PREFIX + "protobuf_unittest.FooProto$NestedInFileClassMessage"); +} + +TEST_F(NameResolverTest, JavaMultipleFilesEnum) { + auto file = BuildFileAndPopulatePool("foo.proto", + R"schema( edition = "2023"; package protobuf_unittest; @@ -243,7 +303,7 @@ TEST_F(NameResolverTest, MultipleFilesEnumEdition2023) { } )schema"); - auto enum_descriptor = pool_.FindEnumTypeByName("protobuf_unittest.FooEnum"); + auto enum_descriptor = file->FindEnumTypeByName("FooEnum"); ClassNameResolver resolver; EXPECT_EQ(resolver.GetClassName(enum_descriptor, /* immutable = */ true), @@ -252,9 +312,9 @@ TEST_F(NameResolverTest, MultipleFilesEnumEdition2023) { PACKAGE_PREFIX "protobuf_unittest.FooEnum"); } -TEST_F(NameResolverTest, SingleFileEnumEdition2023) { - BuildFileAndPopulatePool("foo.proto", - R"schema( +TEST_F(NameResolverTest, JavaMultipleFilesFalseEnum) { + auto file = BuildFileAndPopulatePool("foo.proto", + R"schema( edition = "2023"; package protobuf_unittest; @@ -264,7 +324,7 @@ TEST_F(NameResolverTest, SingleFileEnumEdition2023) { } )schema"); - auto enum_descriptor = pool_.FindEnumTypeByName("protobuf_unittest.FooEnum"); + auto enum_descriptor = file->FindEnumTypeByName("FooEnum"); ClassNameResolver resolver; EXPECT_EQ(resolver.GetClassName(enum_descriptor, /* immutable = */ true), @@ -273,6 +333,41 @@ TEST_F(NameResolverTest, SingleFileEnumEdition2023) { PACKAGE_PREFIX "protobuf_unittest.Foo$FooEnum"); } +TEST_F(NameResolverTest, NestInFileClassEnum) { + auto file = BuildFileAndPopulatePool("foo.proto", + R"schema( + edition = "2024"; + import "third_party/java/protobuf/java_features.proto"; + package protobuf_unittest; + enum NestedInFileClassEnum { + option features.(pb.java).nest_in_file_class = YES; + + FOO_DEFAULT = 0; + FOO_VALUE = 1; + } + + enum UnnestedEnum { + BAR_DEFAULT = 0; + BAR_VALUE = 1; + } + )schema"); + + ClassNameResolver resolver; + auto nested_enum = file->FindEnumTypeByName("NestedInFileClassEnum"); + auto unnested_enum = file->FindEnumTypeByName("UnnestedEnum"); + + EXPECT_EQ(resolver.GetClassName(unnested_enum, + /* immutable = */ true), + PACKAGE_PREFIX "protobuf_unittest.UnnestedEnum"); + EXPECT_EQ(resolver.GetClassName(nested_enum, + /* immutable = */ true), + PACKAGE_PREFIX "protobuf_unittest.FooProto.NestedInFileClassEnum"); + EXPECT_EQ(resolver.GetJavaImmutableClassName(unnested_enum), + PACKAGE_PREFIX "protobuf_unittest.UnnestedEnum"); + EXPECT_EQ(resolver.GetJavaImmutableClassName(nested_enum), + PACKAGE_PREFIX "protobuf_unittest.FooProto$NestedInFileClassEnum"); +} + } // namespace } // namespace java } // namespace compiler diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 575bb8207f89..632372e037ce 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -4800,6 +4800,7 @@ bool DescriptorPool::ResolvesFeaturesForImpl(int extension_number) const { if (absl::c_find_if(fields, [&](const FieldDescriptor* field) { return field->number() == extension_number; }) == fields.end()) { + std::cerr << "MMP " << GetFeatureSetDefaults().DebugString() << "\n"; return false; } } @@ -7876,6 +7877,17 @@ void DescriptorBuilder::ValidateOptions(const FileDescriptor* file, if (file->edition() == Edition::EDITION_PROTO3) { ValidateProto3(file, proto); } + + if (file->edition() >= Edition::EDITION_2024) { + if (file->options().has_java_multiple_files()) { + AddError(file->name(), proto, DescriptorPool::ErrorCollector::OPTION_NAME, + "The file option `java_multiple_files` is not supported in " + "editions 2024 and above, which default to the feature value of" + " `nest_in_file_class = NO` (equivalent to `java_multiple_files " + "= true`). To set and use the legacy `java_multiple_files` " + "option, please set `nest_in_file_class = LEGACY`."); + } + } } void DescriptorBuilder::ValidateProto3(const FileDescriptor* file, diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index 9e8bd68af858..940bcf25dd76 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -53,6 +53,7 @@ #include "google/protobuf/descriptor_lite.h" #include "google/protobuf/extension_set.h" #include "google/protobuf/port.h" +// #include "third_party/protobuf/descriptor.proto.h" // Must be included last. #include "google/protobuf/port_def.inc"