Skip to content

Commit

Permalink
Replace previous breaking changes with deprecation warnings.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mkruskal-google authored and deannagarcia committed Apr 27, 2023
1 parent 2230d0e commit db1d3f8
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 27 deletions.
4 changes: 4 additions & 0 deletions java/core/src/main/java/com/google/protobuf/Descriptors.java
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ public List<FileDescriptor> getPublicDependencies() {
}

/** The syntax of the .proto file. */
@Deprecated
public
enum Syntax {
UNKNOWN("unknown"),
PROTO2("proto2"),
Expand All @@ -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;
Expand Down
57 changes: 34 additions & 23 deletions src/google/protobuf/descriptor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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();
}

Expand Down Expand Up @@ -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();
Expand All @@ -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 {
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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());
});
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 "
Expand All @@ -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;
}
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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(
Expand Down
45 changes: 44 additions & 1 deletion src/google/protobuf/descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@

#ifdef SWIG
#define PROTOBUF_EXPORT
#define PROTOBUF_IGNORE_DEPRECATION_START
#define PROTOBUF_IGNORE_DEPRECATION_STOP
#endif


Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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:

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 {

Expand Down
13 changes: 10 additions & 3 deletions src/google/protobuf/descriptor_legacy.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@

namespace google {
namespace protobuf {
PROTOBUF_IGNORE_DEPRECATION_START

// Wraps FileDescriptor.
class PROTOBUF_EXPORT FileDescriptorLegacy {
Expand All @@ -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:
Expand All @@ -104,6 +110,7 @@ class PROTOBUF_EXPORT OneofDescriptorLegacy {
const OneofDescriptor* desc_;
};

PROTOBUF_IGNORE_DEPRECATION_STOP
} // namespace protobuf
} // namespace google

Expand Down

0 comments on commit db1d3f8

Please sign in to comment.