diff --git a/java/core/src/main/java/com/google/protobuf/Descriptors.java b/java/core/src/main/java/com/google/protobuf/Descriptors.java index be7c76a5b52c1..e866d199b3ca8 100644 --- a/java/core/src/main/java/com/google/protobuf/Descriptors.java +++ b/java/core/src/main/java/com/google/protobuf/Descriptors.java @@ -162,6 +162,8 @@ public List getPublicDependencies() { } /** The syntax of the .proto file. */ + @Deprecated + public enum Syntax { UNKNOWN("unknown"), PROTO2("proto2"), @@ -175,6 +177,8 @@ enum Syntax { } /** Get the syntax of the .proto file. */ + @Deprecated + public Syntax getSyntax() { if (Syntax.PROTO3.name.equals(proto.getSyntax())) { return Syntax.PROTO3; diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index c12e9dcbce0b9..51b6dd9a01c84 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -2612,10 +2612,12 @@ void FileDescriptor::CopyHeadingTo(FileDescriptorProto* proto) const { } // TODO(liujisi): Also populate when syntax="proto2". - if (syntax() == SYNTAX_PROTO3 + FileDescriptorLegacy::Syntax syntax = FileDescriptorLegacy(this).syntax(); + if (syntax == FileDescriptorLegacy::Syntax::SYNTAX_PROTO3 ) { - proto->set_syntax(SyntaxName(syntax())); + proto->set_syntax(FileDescriptorLegacy::SyntaxName(syntax)); } + if (&options() != &FileOptions::default_instance()) { *proto->mutable_options() = options(); } @@ -3010,8 +3012,9 @@ std::string FileDescriptor::DebugStringWithOptions( SourceLocationCommentPrinter syntax_comment(this, path, "", debug_string_options); syntax_comment.AddPreComment(&contents); - absl::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n", - SyntaxName(syntax())); + absl::SubstituteAndAppend( + &contents, "syntax = \"$0\";\n\n", + FileDescriptorLegacy::SyntaxName(FileDescriptorLegacy(this).syntax())); syntax_comment.AddPostComment(&contents); } @@ -3282,7 +3285,7 @@ void FieldDescriptor::DebugString( // Label is omitted for maps, oneof, and plain proto3 fields. if (is_map() || real_containing_oneof() || - (is_optional() && !has_optional_keyword())) { + (is_optional() && !FieldDescriptorLegacy(this).has_optional_keyword())) { label.clear(); } @@ -3573,7 +3576,8 @@ bool FileDescriptor::GetSourceLocation(SourceLocation* out_location) const { bool FieldDescriptor::is_packed() const { if (!is_packable()) return false; - if (file_->syntax() == FileDescriptor::SYNTAX_PROTO2) { + if (FileDescriptorLegacy(file_).syntax() == + FileDescriptorLegacy::Syntax::SYNTAX_PROTO2) { return (options_ != nullptr) && options_->packed(); } else { return options_ == nullptr || !options_->has_packed() || options_->packed(); @@ -3582,7 +3586,8 @@ bool FieldDescriptor::is_packed() const { bool FieldDescriptor::requires_utf8_validation() const { return type() == TYPE_STRING && - file()->syntax() == FileDescriptor::SYNTAX_PROTO3; + FileDescriptorLegacy(file_).syntax() == + FileDescriptorLegacy::Syntax::SYNTAX_PROTO3; } bool Descriptor::GetSourceLocation(SourceLocation* out_location) const { @@ -3989,7 +3994,7 @@ class DescriptorBuilder { const Descriptor* result); void CheckFieldJsonNameUniqueness(const std::string& message_name, const DescriptorProto& message, - FileDescriptor::Syntax syntax, + FileDescriptorLegacy::Syntax syntax, bool use_custom_names); void CheckEnumValueUniqueness(const EnumDescriptorProto& proto, const EnumDescriptor* result); @@ -4711,7 +4716,7 @@ FileDescriptor* DescriptorPool::NewPlaceholderFileWithMutexHeld( placeholder->tables_ = &FileDescriptorTables::GetEmptyInstance(); placeholder->source_code_info_ = &SourceCodeInfo::default_instance(); placeholder->is_placeholder_ = true; - placeholder->syntax_ = FileDescriptor::SYNTAX_UNKNOWN; + placeholder->syntax_ = FileDescriptorLegacy::SYNTAX_UNKNOWN; placeholder->finished_building_ = true; // All other fields are zero or nullptr. @@ -5226,11 +5231,11 @@ FileDescriptor* DescriptorBuilder::BuildFileImpl( // TODO(liujisi): Report error when the syntax is empty after all the protos // have added the syntax statement. if (proto.syntax().empty() || proto.syntax() == "proto2") { - file_->syntax_ = FileDescriptor::SYNTAX_PROTO2; + file_->syntax_ = FileDescriptorLegacy::SYNTAX_PROTO2; } else if (proto.syntax() == "proto3") { - file_->syntax_ = FileDescriptor::SYNTAX_PROTO3; + file_->syntax_ = FileDescriptorLegacy::SYNTAX_PROTO3; } else { - file_->syntax_ = FileDescriptor::SYNTAX_UNKNOWN; + file_->syntax_ = FileDescriptorLegacy::SYNTAX_UNKNOWN; AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, [&] { return absl::StrCat("Unrecognized syntax: ", proto.syntax()); }); @@ -5681,11 +5686,12 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, void DescriptorBuilder::CheckFieldJsonNameUniqueness( const DescriptorProto& proto, const Descriptor* result) { - FileDescriptor::Syntax syntax = result->file()->syntax(); + FileDescriptorLegacy::Syntax syntax = + FileDescriptorLegacy(result->file()).syntax(); std::string message_name = result->full_name(); if (pool_->deprecated_legacy_json_field_conflicts_ || IsLegacyJsonFieldConflictEnabled(result->options())) { - if (syntax == FileDescriptor::SYNTAX_PROTO3) { + if (syntax == FileDescriptorLegacy::Syntax::SYNTAX_PROTO3) { // Only check default JSON names for conflicts in proto3. This is legacy // behavior that will be removed in a later version. CheckFieldJsonNameUniqueness(message_name, proto, syntax, false); @@ -5725,7 +5731,7 @@ bool JsonNameLooksLikeExtension(std::string name) { void DescriptorBuilder::CheckFieldJsonNameUniqueness( const std::string& message_name, const DescriptorProto& message, - FileDescriptor::Syntax syntax, bool use_custom_names) { + FileDescriptorLegacy::Syntax syntax, bool use_custom_names) { absl::flat_hash_map name_to_field; for (const FieldDescriptorProto& field : message.field()) { JsonNameDetails details = GetJsonNameDetails(&field, use_custom_names); @@ -5769,7 +5775,7 @@ void DescriptorBuilder::CheckFieldJsonNameUniqueness( }; bool involves_default = !details.is_custom || !match.is_custom; - if (syntax == FileDescriptor::SYNTAX_PROTO2 && involves_default) { + if (syntax == FileDescriptorLegacy::SYNTAX_PROTO2 && involves_default) { // TODO(b/261750676) Upgrade this to an error once downstream protos have // been fixed. AddWarning(message_name, field, DescriptorPool::ErrorCollector::NAME, @@ -5808,7 +5814,8 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, result->proto3_optional_ = proto.proto3_optional(); if (proto.proto3_optional() && - file_->syntax() != FileDescriptor::SYNTAX_PROTO3) { + FileDescriptorLegacy(file_).syntax() != + FileDescriptorLegacy::Syntax::SYNTAX_PROTO3) { AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, [&] { return absl::StrCat( @@ -6221,7 +6228,8 @@ void DescriptorBuilder::CheckEnumValueUniqueness( // compatibility we issue only a warning for proto2. if ((pool_->deprecated_legacy_json_field_conflicts_ || IsLegacyJsonFieldConflictEnabled(result->options())) && - result->file()->syntax() == FileDescriptor::SYNTAX_PROTO2) { + FileDescriptorLegacy(result->file()).syntax() == + FileDescriptorLegacy::Syntax::SYNTAX_PROTO2) { AddWarning(value->full_name(), proto.value(i), DescriptorPool::ErrorCollector::NAME, make_error); continue; @@ -6585,7 +6593,7 @@ void DescriptorBuilder::CrossLinkMessage(Descriptor* message, const FieldDescriptor* field = message->field(i); if (field->proto3_optional_) { if (!field->containing_oneof() || - !field->containing_oneof()->is_synthetic()) { + !OneofDescriptorLegacy(field->containing_oneof()).is_synthetic()) { AddError(message->full_name(), proto.field(i), DescriptorPool::ErrorCollector::OTHER, "Fields with proto3_optional set must be " @@ -6598,7 +6606,7 @@ void DescriptorBuilder::CrossLinkMessage(Descriptor* message, int first_synthetic = -1; for (int i = 0; i < message->oneof_decl_count(); i++) { const OneofDescriptor* oneof = message->oneof_decl(i); - if (oneof->is_synthetic()) { + if (OneofDescriptorLegacy(oneof).is_synthetic()) { if (first_synthetic == -1) { first_synthetic = i; } @@ -7140,7 +7148,8 @@ void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file, } } } - if (file->syntax() == FileDescriptor::SYNTAX_PROTO3) { + if (FileDescriptorLegacy(file).syntax() == + FileDescriptorLegacy::Syntax::SYNTAX_PROTO3) { ValidateProto3(file, proto); } } @@ -7203,8 +7212,10 @@ void DescriptorBuilder::ValidateProto3Field(FieldDescriptor* field, } if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM && field->enum_type() && - field->enum_type()->file()->syntax() != FileDescriptor::SYNTAX_PROTO3 && - field->enum_type()->file()->syntax() != FileDescriptor::SYNTAX_UNKNOWN) { + FileDescriptorLegacy(field->enum_type()->file()).syntax() != + FileDescriptorLegacy::Syntax::SYNTAX_PROTO3 && + FileDescriptorLegacy(field->enum_type()->file()).syntax() != + FileDescriptorLegacy::Syntax::SYNTAX_UNKNOWN) { // Proto3 messages can only use Proto3 enum types; otherwise we can't // guarantee that the default value is zero. AddError( diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index 97829d2e2f1c7..347f51abfe02d 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -79,6 +79,8 @@ #ifdef SWIG #define PROTOBUF_EXPORT +#define PROTOBUF_IGNORE_DEPRECATION_START +#define PROTOBUF_IGNORE_DEPRECATION_STOP #endif @@ -922,10 +924,17 @@ class PROTOBUF_EXPORT FieldDescriptor : private internal::SymbolBase { friend class Reflection; friend class FieldDescriptorLegacy; + + public: + ABSL_DEPRECATED( + "Syntax is deprecated in favor of editions, please use " + "FieldDescriptor::has_presence instead.") // Returns true if this field was syntactically written with "optional" in the // .proto file. Excludes singular proto3 fields that do not have a label. bool has_optional_keyword() const; + private: + // Fill the json_name field of FieldDescriptorProto. void CopyJsonNameTo(FieldDescriptorProto* proto) const; @@ -1083,10 +1092,17 @@ class PROTOBUF_EXPORT OneofDescriptor : private internal::SymbolBase { friend class compiler::cpp::Formatter; friend class OneofDescriptorLegacy; + + public: + ABSL_DEPRECATED( + "Syntax is deprecated in favor of editions, please use " + "real_oneof_decl_count for now instead of is_synthetic.") // Returns whether this oneof was inserted by the compiler to wrap a proto3 // optional field. If this returns true, code generators should *not* emit it. bool is_synthetic() const; + private: + // See Descriptor::DebugString(). void DebugString(int depth, std::string* contents, const DebugStringOptions& options) const; @@ -1657,12 +1673,18 @@ class PROTOBUF_EXPORT FileDescriptor : private internal::SymbolBase { // descriptor.proto, and any available extensions of that message. const FileOptions& options() const; + private: // With the upcoming release of editions, syntax should not be used for // business logic. Instead, the various feature helpers defined in this file // should be used to query more targeted behaviors. For example: // has_presence, is_closed, requires_utf8_validation. - enum Syntax + enum + ABSL_DEPRECATED( + "Syntax is deprecated in favor of editions. Please use targeted " + "feature helpers instead (e.g. has_presence, is_packed, " + "requires_utf8_validation, etc).") + Syntax #ifndef SWIG : int #endif // !SWIG @@ -1671,13 +1693,22 @@ class PROTOBUF_EXPORT FileDescriptor : private internal::SymbolBase { SYNTAX_PROTO2 = 2, SYNTAX_PROTO3 = 3, }; + PROTOBUF_IGNORE_DEPRECATION_START + ABSL_DEPRECATED( + "Syntax is deprecated in favor of editions. Please use targeted " + "feature helpers instead (e.g. has_presence, is_packed, " + "requires_utf8_validation, etc).") Syntax syntax() const; + PROTOBUF_IGNORE_DEPRECATION_STOP // Define a visibility-restricted wrapper for internal use until the migration // is complete. friend class FileDescriptorLegacy; + PROTOBUF_IGNORE_DEPRECATION_START + ABSL_DEPRECATED("Syntax is deprecated in favor of editions") static const char* SyntaxName(Syntax syntax); + PROTOBUF_IGNORE_DEPRECATION_STOP public: @@ -2314,7 +2345,9 @@ PROTOBUF_DEFINE_ARRAY_ACCESSOR(EnumDescriptor, reserved_range, PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, reserved_name_count, int) inline bool EnumDescriptor::is_closed() const { + PROTOBUF_IGNORE_DEPRECATION_START return file()->syntax() != FileDescriptor::SYNTAX_PROTO3; + PROTOBUF_IGNORE_DEPRECATION_STOP } PROTOBUF_DEFINE_NAME_ACCESSOR(EnumValueDescriptor) @@ -2465,25 +2498,33 @@ inline bool FieldDescriptor::is_map() const { } inline bool FieldDescriptor::has_optional_keyword() const { + PROTOBUF_IGNORE_DEPRECATION_START return proto3_optional_ || (file()->syntax() == FileDescriptor::SYNTAX_PROTO2 && is_optional() && !containing_oneof()); + PROTOBUF_IGNORE_DEPRECATION_STOP } inline const OneofDescriptor* FieldDescriptor::real_containing_oneof() const { + PROTOBUF_IGNORE_DEPRECATION_START auto* oneof = containing_oneof(); return oneof && !oneof->is_synthetic() ? oneof : nullptr; + PROTOBUF_IGNORE_DEPRECATION_STOP } inline bool FieldDescriptor::has_presence() const { + PROTOBUF_IGNORE_DEPRECATION_START if (is_repeated()) return false; return cpp_type() == CPPTYPE_MESSAGE || containing_oneof() || file()->syntax() == FileDescriptor::SYNTAX_PROTO2; + PROTOBUF_IGNORE_DEPRECATION_STOP } inline bool FieldDescriptor::legacy_enum_field_treated_as_closed() const { + PROTOBUF_IGNORE_DEPRECATION_START return type() == TYPE_ENUM && file()->syntax() == FileDescriptor::SYNTAX_PROTO2; + PROTOBUF_IGNORE_DEPRECATION_STOP } // To save space, index() is computed by looking at the descriptor's position @@ -2586,9 +2627,11 @@ inline const FileDescriptor* FileDescriptor::weak_dependency(int index) const { return dependency(weak_dependencies_[index]); } +PROTOBUF_IGNORE_DEPRECATION_START inline FileDescriptor::Syntax FileDescriptor::syntax() const { return static_cast(syntax_); } +PROTOBUF_IGNORE_DEPRECATION_STOP namespace internal { diff --git a/src/google/protobuf/descriptor_legacy.h b/src/google/protobuf/descriptor_legacy.h index 763f4477e8fd7..75b9cfa9ba256 100644 --- a/src/google/protobuf/descriptor_legacy.h +++ b/src/google/protobuf/descriptor_legacy.h @@ -66,6 +66,7 @@ namespace google { namespace protobuf { +PROTOBUF_IGNORE_DEPRECATION_START // Wraps FileDescriptor. class PROTOBUF_EXPORT FileDescriptorLegacy { @@ -74,10 +75,15 @@ class PROTOBUF_EXPORT FileDescriptorLegacy { // Any dependencies on file-level syntax keyword should be replaced by // feature-level switches to support go/protobuf-editions. - using Syntax = FileDescriptor::Syntax; - Syntax syntax() const { return desc_->syntax(); } + enum Syntax { + SYNTAX_UNKNOWN = FileDescriptor::SYNTAX_UNKNOWN, + SYNTAX_PROTO2 = FileDescriptor::SYNTAX_PROTO2, + SYNTAX_PROTO3 = FileDescriptor::SYNTAX_PROTO3, + }; + Syntax syntax() const { return static_cast(desc_->syntax()); } static absl::string_view SyntaxName(Syntax syntax) { - return FileDescriptor::SyntaxName(syntax); + return FileDescriptor::SyntaxName( + static_cast(syntax)); } private: @@ -104,6 +110,7 @@ class PROTOBUF_EXPORT OneofDescriptorLegacy { const OneofDescriptor* desc_; }; +PROTOBUF_IGNORE_DEPRECATION_STOP } // namespace protobuf } // namespace google