Replace previous breaking changes with deprecation warnings.

These changes hid public APIs that are deprecated in advance of protobuf editions.  They will be fully removed in a future release.  Any uses of them should be migrated to the future-facing feature helpers we provide on descriptor classes.

PiperOrigin-RevId: 527422059
pull/12591/head
Mike Kruskal 2 years ago committed by Deanna Garcia
parent 2230d0e748
commit db1d3f8b51
  1. 4
      java/core/src/main/java/com/google/protobuf/Descriptors.java
  2. 57
      src/google/protobuf/descriptor.cc
  3. 45
      src/google/protobuf/descriptor.h
  4. 13
      src/google/protobuf/descriptor_legacy.h

@ -162,6 +162,8 @@ public final class Descriptors {
}
/** The syntax of the .proto file. */
@Deprecated
public
enum Syntax {
UNKNOWN("unknown"),
PROTO2("proto2"),
@ -175,6 +177,8 @@ public final class Descriptors {
}
/** Get the syntax of the .proto file. */
@Deprecated
public
Syntax getSyntax() {
if (Syntax.PROTO3.name.equals(proto.getSyntax())) {
return Syntax.PROTO3;

@ -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<std::string, JsonNameDetails> 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(

@ -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>(syntax_);
}
PROTOBUF_IGNORE_DEPRECATION_STOP
namespace internal {

@ -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<Syntax>(desc_->syntax()); }
static absl::string_view SyntaxName(Syntax syntax) {
return FileDescriptor::SyntaxName(syntax);
return FileDescriptor::SyntaxName(
static_cast<FileDescriptor::Syntax>(syntax));
}
private:
@ -104,6 +110,7 @@ class PROTOBUF_EXPORT OneofDescriptorLegacy {
const OneofDescriptor* desc_;
};
PROTOBUF_IGNORE_DEPRECATION_STOP
} // namespace protobuf
} // namespace google

Loading…
Cancel
Save