Skip to content

Commit

Permalink
Add C# presence methods to proto3 oneof fields.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 514587333
  • Loading branch information
mkruskal-google authored and copybara-github committed Mar 7, 2023
1 parent f174908 commit affadac
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 23 deletions.
20 changes: 4 additions & 16 deletions src/google/protobuf/compiler/csharp/csharp_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,28 +140,16 @@ inline bool IsWrapperType(const FieldDescriptor* descriptor) {
descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";
}

inline bool IsProto2(const FileDescriptor* descriptor) {
return descriptor->syntax() == FileDescriptor::SYNTAX_PROTO2;
}

inline bool SupportsPresenceApi(const FieldDescriptor* descriptor) {
// Unlike most languages, we don't generate Has/Clear members for message
// types, because they can always be set to null in C#. They're not really
// needed for oneof fields in proto2 either, as everything can be done via
// oneof case, but we follow the convention from other languages. Proto3
// oneof fields never have Has/Clear members - but will also never have
// the explicit optional keyword either.
//
// None of the built-in helpers (descriptor->has_presence() etc) describe
// quite the behavior we want, so the rules are explicit below.

if (descriptor->is_repeated() ||
descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
// oneof case, but we follow the convention from other languages.
if (descriptor->type() == FieldDescriptor::TYPE_MESSAGE) {
return false;
}
// has_optional_keyword() has more complex rules for proto2, but that
// doesn't matter given the first part of this condition.
return IsProto2(descriptor->file()) || descriptor->has_optional_keyword();

return descriptor->has_presence();
}

inline bool RequiresPresenceBit(const FieldDescriptor* descriptor) {
Expand Down
12 changes: 5 additions & 7 deletions src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,18 +67,16 @@ PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {
}

void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) {

// Note: in multiple places, this code assumes that all fields
// that support presence are either nullable, or use a presence field bit.
// Fields which are oneof members are not generated here; they're generated in PrimitiveOneofFieldGenerator below.
// Extensions are not generated here either.


// Proto2 allows different default values to be specified. These are retained
// via static fields. They don't particularly need to be, but we don't need
// to change that. In Proto3 the default value we don't generate these
// fields, just using the literal instead.
if (IsProto2(descriptor_->file())) {
// Explicit presence allows different default values to be specified. These
// are retained via static fields. They don't particularly need to be, but we
// don't need to change that. Under implicit presence we don't use static
// fields for default values and just use the literals instead.
if (descriptor_->has_presence()) {
// Note: "private readonly static" isn't as idiomatic as
// "private static readonly", but changing this now would create a lot of
// churn in generated code with near-to-zero benefit.
Expand Down

0 comments on commit affadac

Please sign in to comment.