diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h index 5960aa170d..f3b165a9f1 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.h +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h @@ -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) { diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index a0bd2e4702..457dd976fb 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -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.