Merge pull request #7491 from haberman/cherry

Cherry-pick fixes onto 3.12.x branch for 3.12.0-rc2
pull/7494/head
Joshua Haberman 5 years ago committed by GitHub
commit 51199fcba2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 142
      csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs
  2. 924
      csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs
  3. 150
      csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs
  4. 171
      csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs
  5. 6
      csharp/src/Google.Protobuf/Extension.cs
  6. 240
      csharp/src/Google.Protobuf/Reflection/Descriptor.cs
  7. 12
      csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs
  8. 12
      csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs
  9. 29
      csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
  10. 12
      csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
  11. 12
      csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
  12. 12
      csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs
  13. 12
      csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs
  14. 12
      csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs
  15. 93
      csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
  16. 1
      java/core/generate-test-sources-build.xml
  17. 108
      java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
  18. 20
      java/core/src/test/java/com/google/protobuf/TextFormatTest.java
  19. 1
      java/lite/generate-test-sources-build.xml
  20. 5
      python/google/protobuf/internal/test_proto3_optional.proto
  21. 33
      src/google/protobuf/compiler/csharp/csharp_helpers.h
  22. 1
      src/google/protobuf/compiler/java/java_enum_field.cc
  23. 2
      src/google/protobuf/generated_message_reflection.cc
  24. 12
      src/google/protobuf/proto3_arena_unittest.cc
  25. 4
      src/google/protobuf/unittest_proto3_optional.proto

@ -290,13 +290,13 @@ namespace ProtobufTestMessages.Proto2 {
optionalBool_ = other.optionalBool_;
optionalString_ = other.optionalString_;
optionalBytes_ = other.optionalBytes_;
optionalNestedMessage_ = other.HasOptionalNestedMessage ? other.optionalNestedMessage_.Clone() : null;
optionalForeignMessage_ = other.HasOptionalForeignMessage ? other.optionalForeignMessage_.Clone() : null;
optionalNestedMessage_ = other.optionalNestedMessage_ != null ? other.optionalNestedMessage_.Clone() : null;
optionalForeignMessage_ = other.optionalForeignMessage_ != null ? other.optionalForeignMessage_.Clone() : null;
optionalNestedEnum_ = other.optionalNestedEnum_;
optionalForeignEnum_ = other.optionalForeignEnum_;
optionalStringPiece_ = other.optionalStringPiece_;
optionalCord_ = other.optionalCord_;
recursiveMessage_ = other.HasRecursiveMessage ? other.recursiveMessage_.Clone() : null;
recursiveMessage_ = other.recursiveMessage_ != null ? other.recursiveMessage_.Clone() : null;
repeatedInt32_ = other.repeatedInt32_.Clone();
repeatedInt64_ = other.repeatedInt64_.Clone();
repeatedUint32_ = other.repeatedUint32_.Clone();
@ -794,16 +794,6 @@ namespace ProtobufTestMessages.Proto2 {
optionalNestedMessage_ = value;
}
}
/// <summary>Gets whether the optional_nested_message field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasOptionalNestedMessage {
get { return optionalNestedMessage_ != null; }
}
/// <summary>Clears the value of the optional_nested_message field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearOptionalNestedMessage() {
optionalNestedMessage_ = null;
}
/// <summary>Field number for the "optional_foreign_message" field.</summary>
public const int OptionalForeignMessageFieldNumber = 19;
@ -815,16 +805,6 @@ namespace ProtobufTestMessages.Proto2 {
optionalForeignMessage_ = value;
}
}
/// <summary>Gets whether the optional_foreign_message field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasOptionalForeignMessage {
get { return optionalForeignMessage_ != null; }
}
/// <summary>Clears the value of the optional_foreign_message field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearOptionalForeignMessage() {
optionalForeignMessage_ = null;
}
/// <summary>Field number for the "optional_nested_enum" field.</summary>
public const int OptionalNestedEnumFieldNumber = 21;
@ -930,16 +910,6 @@ namespace ProtobufTestMessages.Proto2 {
recursiveMessage_ = value;
}
}
/// <summary>Gets whether the recursive_message field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasRecursiveMessage {
get { return recursiveMessage_ != null; }
}
/// <summary>Clears the value of the recursive_message field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearRecursiveMessage() {
recursiveMessage_ = null;
}
/// <summary>Field number for the "repeated_int32" field.</summary>
public const int RepeatedInt32FieldNumber = 31;
@ -1660,24 +1630,12 @@ namespace ProtobufTestMessages.Proto2 {
public const int OneofNestedMessageFieldNumber = 112;
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage OneofNestedMessage {
get { return HasOneofNestedMessage ? (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage) oneofField_ : null; }
get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage) oneofField_ : null; }
set {
oneofField_ = value;
oneofFieldCase_ = value == null ? OneofFieldOneofCase.None : OneofFieldOneofCase.OneofNestedMessage;
}
}
/// <summary>Gets whether the "oneof_nested_message" field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasOneofNestedMessage {
get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; }
}
/// <summary> Clears the value of the oneof if it's currently set to "oneof_nested_message" </summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearOneofNestedMessage() {
if (HasOneofNestedMessage) {
ClearOneofField();
}
}
/// <summary>Field number for the "oneof_string" field.</summary>
public const int OneofStringFieldNumber = 113;
@ -2479,13 +2437,13 @@ namespace ProtobufTestMessages.Proto2 {
if (HasOptionalBool) hash ^= OptionalBool.GetHashCode();
if (HasOptionalString) hash ^= OptionalString.GetHashCode();
if (HasOptionalBytes) hash ^= OptionalBytes.GetHashCode();
if (HasOptionalNestedMessage) hash ^= OptionalNestedMessage.GetHashCode();
if (HasOptionalForeignMessage) hash ^= OptionalForeignMessage.GetHashCode();
if (optionalNestedMessage_ != null) hash ^= OptionalNestedMessage.GetHashCode();
if (optionalForeignMessage_ != null) hash ^= OptionalForeignMessage.GetHashCode();
if (HasOptionalNestedEnum) hash ^= OptionalNestedEnum.GetHashCode();
if (HasOptionalForeignEnum) hash ^= OptionalForeignEnum.GetHashCode();
if (HasOptionalStringPiece) hash ^= OptionalStringPiece.GetHashCode();
if (HasOptionalCord) hash ^= OptionalCord.GetHashCode();
if (HasRecursiveMessage) hash ^= RecursiveMessage.GetHashCode();
if (recursiveMessage_ != null) hash ^= RecursiveMessage.GetHashCode();
hash ^= repeatedInt32_.GetHashCode();
hash ^= repeatedInt64_.GetHashCode();
hash ^= repeatedUint32_.GetHashCode();
@ -2555,7 +2513,7 @@ namespace ProtobufTestMessages.Proto2 {
hash ^= MapStringNestedEnum.GetHashCode();
hash ^= MapStringForeignEnum.GetHashCode();
if (HasOneofUint32) hash ^= OneofUint32.GetHashCode();
if (HasOneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode();
if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) hash ^= OneofNestedMessage.GetHashCode();
if (HasOneofString) hash ^= OneofString.GetHashCode();
if (HasOneofBytes) hash ^= OneofBytes.GetHashCode();
if (HasOneofBool) hash ^= OneofBool.GetHashCode();
@ -2659,11 +2617,11 @@ namespace ProtobufTestMessages.Proto2 {
output.WriteRawTag(122);
output.WriteBytes(OptionalBytes);
}
if (HasOptionalNestedMessage) {
if (optionalNestedMessage_ != null) {
output.WriteRawTag(146, 1);
output.WriteMessage(OptionalNestedMessage);
}
if (HasOptionalForeignMessage) {
if (optionalForeignMessage_ != null) {
output.WriteRawTag(154, 1);
output.WriteMessage(OptionalForeignMessage);
}
@ -2683,7 +2641,7 @@ namespace ProtobufTestMessages.Proto2 {
output.WriteRawTag(202, 1);
output.WriteString(OptionalCord);
}
if (HasRecursiveMessage) {
if (recursiveMessage_ != null) {
output.WriteRawTag(218, 1);
output.WriteMessage(RecursiveMessage);
}
@ -2759,7 +2717,7 @@ namespace ProtobufTestMessages.Proto2 {
output.WriteRawTag(248, 6);
output.WriteUInt32(OneofUint32);
}
if (HasOneofNestedMessage) {
if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
output.WriteRawTag(130, 7);
output.WriteMessage(OneofNestedMessage);
}
@ -2924,10 +2882,10 @@ namespace ProtobufTestMessages.Proto2 {
if (HasOptionalBytes) {
size += 1 + pb::CodedOutputStream.ComputeBytesSize(OptionalBytes);
}
if (HasOptionalNestedMessage) {
if (optionalNestedMessage_ != null) {
size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalNestedMessage);
}
if (HasOptionalForeignMessage) {
if (optionalForeignMessage_ != null) {
size += 2 + pb::CodedOutputStream.ComputeMessageSize(OptionalForeignMessage);
}
if (HasOptionalNestedEnum) {
@ -2942,7 +2900,7 @@ namespace ProtobufTestMessages.Proto2 {
if (HasOptionalCord) {
size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalCord);
}
if (HasRecursiveMessage) {
if (recursiveMessage_ != null) {
size += 2 + pb::CodedOutputStream.ComputeMessageSize(RecursiveMessage);
}
size += repeatedInt32_.CalculateSize(_repeated_repeatedInt32_codec);
@ -3016,7 +2974,7 @@ namespace ProtobufTestMessages.Proto2 {
if (HasOneofUint32) {
size += 2 + pb::CodedOutputStream.ComputeUInt32Size(OneofUint32);
}
if (HasOneofNestedMessage) {
if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
size += 2 + pb::CodedOutputStream.ComputeMessageSize(OneofNestedMessage);
}
if (HasOneofString) {
@ -3156,14 +3114,14 @@ namespace ProtobufTestMessages.Proto2 {
if (other.HasOptionalBytes) {
OptionalBytes = other.OptionalBytes;
}
if (other.HasOptionalNestedMessage) {
if (!HasOptionalNestedMessage) {
if (other.optionalNestedMessage_ != null) {
if (optionalNestedMessage_ == null) {
OptionalNestedMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage();
}
OptionalNestedMessage.MergeFrom(other.OptionalNestedMessage);
}
if (other.HasOptionalForeignMessage) {
if (!HasOptionalForeignMessage) {
if (other.optionalForeignMessage_ != null) {
if (optionalForeignMessage_ == null) {
OptionalForeignMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2();
}
OptionalForeignMessage.MergeFrom(other.OptionalForeignMessage);
@ -3180,8 +3138,8 @@ namespace ProtobufTestMessages.Proto2 {
if (other.HasOptionalCord) {
OptionalCord = other.OptionalCord;
}
if (other.HasRecursiveMessage) {
if (!HasRecursiveMessage) {
if (other.recursiveMessage_ != null) {
if (recursiveMessage_ == null) {
RecursiveMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2();
}
RecursiveMessage.MergeFrom(other.RecursiveMessage);
@ -3422,14 +3380,14 @@ namespace ProtobufTestMessages.Proto2 {
break;
}
case 146: {
if (!HasOptionalNestedMessage) {
if (optionalNestedMessage_ == null) {
OptionalNestedMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage();
}
input.ReadMessage(OptionalNestedMessage);
break;
}
case 154: {
if (!HasOptionalForeignMessage) {
if (optionalForeignMessage_ == null) {
OptionalForeignMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2();
}
input.ReadMessage(OptionalForeignMessage);
@ -3452,7 +3410,7 @@ namespace ProtobufTestMessages.Proto2 {
break;
}
case 218: {
if (!HasRecursiveMessage) {
if (recursiveMessage_ == null) {
RecursiveMessage = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2();
}
input.ReadMessage(RecursiveMessage);
@ -3779,7 +3737,7 @@ namespace ProtobufTestMessages.Proto2 {
}
case 898: {
global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage subBuilder = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.NestedMessage();
if (HasOneofNestedMessage) {
if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) {
subBuilder.MergeFrom(OneofNestedMessage);
}
input.ReadMessage(subBuilder);
@ -3962,7 +3920,7 @@ namespace ProtobufTestMessages.Proto2 {
public NestedMessage(NestedMessage other) : this() {
_hasBits0 = other._hasBits0;
a_ = other.a_;
corecursive_ = other.HasCorecursive ? other.corecursive_.Clone() : null;
corecursive_ = other.corecursive_ != null ? other.corecursive_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@ -4005,16 +3963,6 @@ namespace ProtobufTestMessages.Proto2 {
corecursive_ = value;
}
}
/// <summary>Gets whether the corecursive field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasCorecursive {
get { return corecursive_ != null; }
}
/// <summary>Clears the value of the corecursive field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearCorecursive() {
corecursive_ = null;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
@ -4038,7 +3986,7 @@ namespace ProtobufTestMessages.Proto2 {
public override int GetHashCode() {
int hash = 1;
if (HasA) hash ^= A.GetHashCode();
if (HasCorecursive) hash ^= Corecursive.GetHashCode();
if (corecursive_ != null) hash ^= Corecursive.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
@ -4056,7 +4004,7 @@ namespace ProtobufTestMessages.Proto2 {
output.WriteRawTag(8);
output.WriteInt32(A);
}
if (HasCorecursive) {
if (corecursive_ != null) {
output.WriteRawTag(18);
output.WriteMessage(Corecursive);
}
@ -4071,7 +4019,7 @@ namespace ProtobufTestMessages.Proto2 {
if (HasA) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(A);
}
if (HasCorecursive) {
if (corecursive_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Corecursive);
}
if (_unknownFields != null) {
@ -4088,8 +4036,8 @@ namespace ProtobufTestMessages.Proto2 {
if (other.HasA) {
A = other.A;
}
if (other.HasCorecursive) {
if (!HasCorecursive) {
if (other.corecursive_ != null) {
if (corecursive_ == null) {
Corecursive = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2();
}
Corecursive.MergeFrom(other.Corecursive);
@ -4110,7 +4058,7 @@ namespace ProtobufTestMessages.Proto2 {
break;
}
case 18: {
if (!HasCorecursive) {
if (corecursive_ == null) {
Corecursive = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2();
}
input.ReadMessage(Corecursive);
@ -4937,7 +4885,7 @@ namespace ProtobufTestMessages.Proto2 {
_hasBits0 = other._hasBits0;
optionalInt32_ = other.optionalInt32_;
optionalString_ = other.optionalString_;
nestedMessage_ = other.HasNestedMessage ? other.nestedMessage_.Clone() : null;
nestedMessage_ = other.nestedMessage_ != null ? other.nestedMessage_.Clone() : null;
optionalGroup_ = other.HasOptionalGroup ? other.optionalGroup_.Clone() : null;
optionalBool_ = other.optionalBool_;
repeatedInt32_ = other.repeatedInt32_.Clone();
@ -5006,16 +4954,6 @@ namespace ProtobufTestMessages.Proto2 {
nestedMessage_ = value;
}
}
/// <summary>Gets whether the nested_message field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasNestedMessage {
get { return nestedMessage_ != null; }
}
/// <summary>Clears the value of the nested_message field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearNestedMessage() {
nestedMessage_ = null;
}
/// <summary>Field number for the "optionalgroup" field.</summary>
public const int OptionalGroupFieldNumber = 1004;
@ -5099,7 +5037,7 @@ namespace ProtobufTestMessages.Proto2 {
int hash = 1;
if (HasOptionalInt32) hash ^= OptionalInt32.GetHashCode();
if (HasOptionalString) hash ^= OptionalString.GetHashCode();
if (HasNestedMessage) hash ^= NestedMessage.GetHashCode();
if (nestedMessage_ != null) hash ^= NestedMessage.GetHashCode();
if (HasOptionalGroup) hash ^= OptionalGroup.GetHashCode();
if (HasOptionalBool) hash ^= OptionalBool.GetHashCode();
hash ^= repeatedInt32_.GetHashCode();
@ -5124,7 +5062,7 @@ namespace ProtobufTestMessages.Proto2 {
output.WriteRawTag(210, 62);
output.WriteString(OptionalString);
}
if (HasNestedMessage) {
if (nestedMessage_ != null) {
output.WriteRawTag(218, 62);
output.WriteMessage(NestedMessage);
}
@ -5152,7 +5090,7 @@ namespace ProtobufTestMessages.Proto2 {
if (HasOptionalString) {
size += 2 + pb::CodedOutputStream.ComputeStringSize(OptionalString);
}
if (HasNestedMessage) {
if (nestedMessage_ != null) {
size += 2 + pb::CodedOutputStream.ComputeMessageSize(NestedMessage);
}
if (HasOptionalGroup) {
@ -5179,8 +5117,8 @@ namespace ProtobufTestMessages.Proto2 {
if (other.HasOptionalString) {
OptionalString = other.OptionalString;
}
if (other.HasNestedMessage) {
if (!HasNestedMessage) {
if (other.nestedMessage_ != null) {
if (nestedMessage_ == null) {
NestedMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2();
}
NestedMessage.MergeFrom(other.NestedMessage);
@ -5215,7 +5153,7 @@ namespace ProtobufTestMessages.Proto2 {
break;
}
case 8026: {
if (!HasNestedMessage) {
if (nestedMessage_ == null) {
NestedMessage = new global::ProtobufTestMessages.Proto2.ForeignMessageProto2();
}
input.ReadMessage(NestedMessage);

File diff suppressed because it is too large Load Diff

@ -71,25 +71,49 @@ namespace Google.Protobuf.Test.Reflection
};
}
[Test]
public void BuiltinOptionsCanBeRetrieved()
{
// non-custom options (that are not extensions but regular fields) can only be accessed via descriptor.Options
var fileOptions = UnittestProto3Reflection.Descriptor.GetOptions();
Assert.AreEqual("Google.Protobuf.TestProtos", fileOptions.CsharpNamespace);
}
[Test]
public void OptionPresenceCanBeDetected()
{
// case 1: the descriptor has no options at all so the options message is not present
Assert.IsNull(TestAllTypes.Descriptor.GetOptions());
// case 2: the descriptor has some options, but not the one we're looking for
// HasExtension will be false and GetExtension returns extension's default value
Assert.IsFalse(UnittestProto3Reflection.Descriptor.GetOptions().HasExtension(FileOpt1));
Assert.AreEqual(0, UnittestProto3Reflection.Descriptor.GetOptions().GetExtension(FileOpt1));
// case 3: option is present
Assert.IsTrue(UnittestCustomOptionsProto3Reflection.Descriptor.GetOptions().HasExtension(FileOpt1));
Assert.AreEqual(9876543210UL, UnittestCustomOptionsProto3Reflection.Descriptor.GetOptions().GetExtension(FileOpt1));
}
[Test]
public void ScalarOptions()
{
var d = CustomOptionOtherValues.Descriptor;
var options = d.CustomOptions;
AssertOption(-100, options.TryGetInt32, Int32Opt, d.GetOption);
AssertOption(12.3456789f, options.TryGetFloat, FloatOpt, d.GetOption);
AssertOption(1.234567890123456789d, options.TryGetDouble, DoubleOpt, d.GetOption);
AssertOption("Hello, \"World\"", options.TryGetString, StringOpt, d.GetOption);
AssertOption(ByteString.CopyFromUtf8("Hello\0World"), options.TryGetBytes, BytesOpt, d.GetOption);
AssertOption(TestEnumType.TestOptionEnumType2, EnumFetcher<TestEnumType>(options), EnumOpt, d.GetOption);
var customOptions = d.CustomOptions;
AssertOption(-100, customOptions.TryGetInt32, Int32Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(12.3456789f, customOptions.TryGetFloat, FloatOpt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(1.234567890123456789d, customOptions.TryGetDouble, DoubleOpt, d.GetOption, d.GetOptions().GetExtension);
AssertOption("Hello, \"World\"", customOptions.TryGetString, StringOpt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(ByteString.CopyFromUtf8("Hello\0World"), customOptions.TryGetBytes, BytesOpt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(TestEnumType.TestOptionEnumType2, EnumFetcher<TestEnumType>(customOptions), EnumOpt, d.GetOption, d.GetOptions().GetExtension);
}
[Test]
public void MessageOptions()
{
var d = VariousComplexOptions.Descriptor;
var options = d.CustomOptions;
AssertOption(new ComplexOptionType1 { Foo = 42, Foo4 = { 99, 88 } }, options.TryGetMessage, ComplexOpt1, d.GetOption);
var customOptions = d.CustomOptions;
AssertOption(new ComplexOptionType1 { Foo = 42, Foo4 = { 99, 88 } }, customOptions.TryGetMessage, ComplexOpt1, d.GetOption, d.GetOptions().GetExtension);
AssertOption(new ComplexOptionType2
{
Baz = 987,
@ -97,85 +121,84 @@ namespace Google.Protobuf.Test.Reflection
Fred = new ComplexOptionType4 { Waldo = 321 },
Barney = { new ComplexOptionType4 { Waldo = 101 }, new ComplexOptionType4 { Waldo = 212 } }
},
options.TryGetMessage, ComplexOpt2, d.GetOption);
AssertOption(new ComplexOptionType3 { Qux = 9 }, options.TryGetMessage, ComplexOpt3, d.GetOption);
customOptions.TryGetMessage, ComplexOpt2, d.GetOption, d.GetOptions().GetExtension);
AssertOption(new ComplexOptionType3 { Qux = 9 }, customOptions.TryGetMessage, ComplexOpt3, d.GetOption, d.GetOptions().GetExtension);
}
[Test]
public void OptionLocations()
{
var fileOptions = UnittestCustomOptionsProto3Reflection.Descriptor.CustomOptions;
AssertOption(9876543210UL, fileOptions.TryGetUInt64, FileOpt1, UnittestCustomOptionsProto3Reflection.Descriptor.GetOption);
var fileDescriptor = UnittestCustomOptionsProto3Reflection.Descriptor;
AssertOption(9876543210UL, fileDescriptor.CustomOptions.TryGetUInt64, FileOpt1, fileDescriptor.GetOption, fileDescriptor.GetOptions().GetExtension);
var messageOptions = TestMessageWithCustomOptions.Descriptor.CustomOptions;
AssertOption(-56, messageOptions.TryGetInt32, MessageOpt1, TestMessageWithCustomOptions.Descriptor.GetOption);
var messageDescriptor = TestMessageWithCustomOptions.Descriptor;
AssertOption(-56, messageDescriptor.CustomOptions.TryGetInt32, MessageOpt1, messageDescriptor.GetOption, messageDescriptor.GetOptions().GetExtension);
var fieldOptions = TestMessageWithCustomOptions.Descriptor.Fields["field1"].CustomOptions;
AssertOption(8765432109UL, fieldOptions.TryGetFixed64, FieldOpt1, TestMessageWithCustomOptions.Descriptor.Fields["field1"].GetOption);
var fieldDescriptor = TestMessageWithCustomOptions.Descriptor.Fields["field1"];
AssertOption(8765432109UL, fieldDescriptor.CustomOptions.TryGetFixed64, FieldOpt1, fieldDescriptor.GetOption, fieldDescriptor.GetOptions().GetExtension);
var oneofOptions = TestMessageWithCustomOptions.Descriptor.Oneofs[0].CustomOptions;
AssertOption(-99, oneofOptions.TryGetInt32, OneofOpt1, TestMessageWithCustomOptions.Descriptor.Oneofs[0].GetOption);
var oneofDescriptor = TestMessageWithCustomOptions.Descriptor.Oneofs[0];
AssertOption(-99, oneofDescriptor.CustomOptions.TryGetInt32, OneofOpt1, oneofDescriptor.GetOption, oneofDescriptor.GetOptions().GetExtension);
var enumOptions = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].CustomOptions;
AssertOption(-789, enumOptions.TryGetSFixed32, EnumOpt1, TestMessageWithCustomOptions.Descriptor.EnumTypes[0].GetOption);
var enumDescriptor = TestMessageWithCustomOptions.Descriptor.EnumTypes[0];
AssertOption(-789, enumDescriptor.CustomOptions.TryGetSFixed32, EnumOpt1, enumDescriptor.GetOption, enumDescriptor.GetOptions().GetExtension);
var enumValueOptions = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].FindValueByNumber(2).CustomOptions;
AssertOption(123, enumValueOptions.TryGetInt32, EnumValueOpt1, TestMessageWithCustomOptions.Descriptor.EnumTypes[0].FindValueByNumber(2).GetOption);
var enumValueDescriptor = TestMessageWithCustomOptions.Descriptor.EnumTypes[0].FindValueByNumber(2);
AssertOption(123, enumValueDescriptor.CustomOptions.TryGetInt32, EnumValueOpt1, enumValueDescriptor.GetOption, enumValueDescriptor.GetOptions().GetExtension);
var service = UnittestCustomOptionsProto3Reflection.Descriptor.Services
var serviceDescriptor = UnittestCustomOptionsProto3Reflection.Descriptor.Services
.Single(s => s.Name == "TestServiceWithCustomOptions");
var serviceOptions = service.CustomOptions;
AssertOption(-9876543210, serviceOptions.TryGetSInt64, ServiceOpt1, service.GetOption);
AssertOption(-9876543210, serviceDescriptor.CustomOptions.TryGetSInt64, ServiceOpt1, serviceDescriptor.GetOption, serviceDescriptor.GetOptions().GetExtension);
var methodOptions = service.Methods[0].CustomOptions;
AssertOption(UnitTest.Issues.TestProtos.MethodOpt1.Val2, EnumFetcher<UnitTest.Issues.TestProtos.MethodOpt1>(methodOptions), UnittestCustomOptionsProto3Extensions.MethodOpt1, service.Methods[0].GetOption);
var methodDescriptor = serviceDescriptor.Methods[0];
AssertOption(UnitTest.Issues.TestProtos.MethodOpt1.Val2, EnumFetcher<UnitTest.Issues.TestProtos.MethodOpt1>(methodDescriptor.CustomOptions), UnittestCustomOptionsProto3Extensions.MethodOpt1, methodDescriptor.GetOption, methodDescriptor.GetOptions().GetExtension);
}
[Test]
public void MinValues()
{
var d = CustomOptionMinIntegerValues.Descriptor;
var options = d.CustomOptions;
AssertOption(false, options.TryGetBool, BoolOpt, d.GetOption);
AssertOption(int.MinValue, options.TryGetInt32, Int32Opt, d.GetOption);
AssertOption(long.MinValue, options.TryGetInt64, Int64Opt, d.GetOption);
AssertOption(uint.MinValue, options.TryGetUInt32, Uint32Opt, d.GetOption);
AssertOption(ulong.MinValue, options.TryGetUInt64, Uint64Opt, d.GetOption);
AssertOption(int.MinValue, options.TryGetSInt32, Sint32Opt, d.GetOption);
AssertOption(long.MinValue, options.TryGetSInt64, Sint64Opt, d.GetOption);
AssertOption(uint.MinValue, options.TryGetUInt32, Fixed32Opt, d.GetOption);
AssertOption(ulong.MinValue, options.TryGetUInt64, Fixed64Opt, d.GetOption);
AssertOption(int.MinValue, options.TryGetInt32, Sfixed32Opt, d.GetOption);
AssertOption(long.MinValue, options.TryGetInt64, Sfixed64Opt, d.GetOption);
var customOptions = d.CustomOptions;
AssertOption(false, customOptions.TryGetBool, BoolOpt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(int.MinValue, customOptions.TryGetInt32, Int32Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(long.MinValue, customOptions.TryGetInt64, Int64Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(uint.MinValue, customOptions.TryGetUInt32, Uint32Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(ulong.MinValue, customOptions.TryGetUInt64, Uint64Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(int.MinValue, customOptions.TryGetSInt32, Sint32Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(long.MinValue, customOptions.TryGetSInt64, Sint64Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(uint.MinValue, customOptions.TryGetUInt32, Fixed32Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(ulong.MinValue, customOptions.TryGetUInt64, Fixed64Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(int.MinValue, customOptions.TryGetInt32, Sfixed32Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(long.MinValue, customOptions.TryGetInt64, Sfixed64Opt, d.GetOption, d.GetOptions().GetExtension);
}
[Test]
public void MaxValues()
{
var d = CustomOptionMaxIntegerValues.Descriptor;
var options = d.CustomOptions;
AssertOption(true, options.TryGetBool, BoolOpt, d.GetOption);
AssertOption(int.MaxValue, options.TryGetInt32, Int32Opt, d.GetOption);
AssertOption(long.MaxValue, options.TryGetInt64, Int64Opt, d.GetOption);
AssertOption(uint.MaxValue, options.TryGetUInt32, Uint32Opt, d.GetOption);
AssertOption(ulong.MaxValue, options.TryGetUInt64, Uint64Opt, d.GetOption);
AssertOption(int.MaxValue, options.TryGetSInt32, Sint32Opt, d.GetOption);
AssertOption(long.MaxValue, options.TryGetSInt64, Sint64Opt, d.GetOption);
AssertOption(uint.MaxValue, options.TryGetFixed32, Fixed32Opt, d.GetOption);
AssertOption(ulong.MaxValue, options.TryGetFixed64, Fixed64Opt, d.GetOption);
AssertOption(int.MaxValue, options.TryGetSFixed32, Sfixed32Opt, d.GetOption);
AssertOption(long.MaxValue, options.TryGetSFixed64, Sfixed64Opt, d.GetOption);
var customOptions = d.CustomOptions;
AssertOption(true, customOptions.TryGetBool, BoolOpt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(int.MaxValue, customOptions.TryGetInt32, Int32Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(long.MaxValue, customOptions.TryGetInt64, Int64Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(uint.MaxValue, customOptions.TryGetUInt32, Uint32Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(ulong.MaxValue, customOptions.TryGetUInt64, Uint64Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(int.MaxValue, customOptions.TryGetSInt32, Sint32Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(long.MaxValue, customOptions.TryGetSInt64, Sint64Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(uint.MaxValue, customOptions.TryGetFixed32, Fixed32Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(ulong.MaxValue, customOptions.TryGetFixed64, Fixed64Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(int.MaxValue, customOptions.TryGetSFixed32, Sfixed32Opt, d.GetOption, d.GetOptions().GetExtension);
AssertOption(long.MaxValue, customOptions.TryGetSFixed64, Sfixed64Opt, d.GetOption, d.GetOptions().GetExtension);
}
[Test]
public void AggregateOptions()
{
// Just two examples
var messageOptions = AggregateMessage.Descriptor.CustomOptions;
AssertOption(new Aggregate { I = 101, S = "MessageAnnotation" }, messageOptions.TryGetMessage, Msgopt, AggregateMessage.Descriptor.GetOption);
var messageDescriptor = AggregateMessage.Descriptor;
AssertOption(new Aggregate { I = 101, S = "MessageAnnotation" }, messageDescriptor.CustomOptions.TryGetMessage, Msgopt, messageDescriptor.GetOption, messageDescriptor.GetOptions().GetExtension);
var fieldOptions = AggregateMessage.Descriptor.Fields["fieldname"].CustomOptions;
AssertOption(new Aggregate { S = "FieldAnnotation" }, fieldOptions.TryGetMessage, Fieldopt, AggregateMessage.Descriptor.Fields["fieldname"].GetOption);
var fieldDescriptor = messageDescriptor.Fields["fieldname"];
AssertOption(new Aggregate { S = "FieldAnnotation" }, fieldDescriptor.CustomOptions.TryGetMessage, Fieldopt, fieldDescriptor.GetOption, fieldDescriptor.GetOptions().GetExtension);
}
[Test]
@ -199,16 +222,19 @@ namespace Google.Protobuf.Test.Reflection
var descriptor = UnittestIssue6936CReflection.Descriptor;
var foo = Foo.Descriptor;
var bar = Bar.Descriptor;
AssertOption("foo", foo.CustomOptions.TryGetString, UnittestIssue6936AExtensions.Opt, foo.GetOption);
AssertOption("bar", bar.CustomOptions.TryGetString, UnittestIssue6936AExtensions.Opt, bar.GetOption);
AssertOption("foo", foo.CustomOptions.TryGetString, UnittestIssue6936AExtensions.Opt, foo.GetOption, foo.GetOptions().GetExtension);
AssertOption("bar", bar.CustomOptions.TryGetString, UnittestIssue6936AExtensions.Opt, bar.GetOption, bar.GetOptions().GetExtension);
}
private void AssertOption<T, D>(T expected, OptionFetcher<T> fetcher, Extension<D, T> extension, Func<Extension<D, T>, T> descriptorOptionFetcher) where D : IExtendableMessage<D>
private void AssertOption<T, D>(T expected, OptionFetcher<T> customOptionFetcher, Extension<D, T> extension, Func<Extension<D, T>, T> getOptionFetcher, Func<Extension<D, T>, T> extensionFetcher) where D : IExtendableMessage<D>
{
T customOptionsValue;
T extensionValue = descriptorOptionFetcher(extension);
Assert.IsTrue(fetcher(extension.FieldNumber, out customOptionsValue));
Assert.IsTrue(customOptionFetcher(extension.FieldNumber, out T customOptionsValue));
Assert.AreEqual(expected, customOptionsValue);
T getOptionValue = getOptionFetcher(extension);
Assert.AreEqual(expected, getOptionValue);
T extensionValue = extensionFetcher(extension);
Assert.AreEqual(expected, extensionValue);
}
}

@ -98,7 +98,48 @@ namespace Google.Protobuf.Reflection
}
[Test]
public void HasValue_Proto3()
public void HasValue_Proto3_Message()
{
var message = new TestAllTypes();
var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].Accessor;
Assert.False(accessor.HasValue(message));
message.SingleForeignMessage = new ForeignMessage();
Assert.True(accessor.HasValue(message));
message.SingleForeignMessage = null;
Assert.False(accessor.HasValue(message));
}
[Test]
public void HasValue_Proto3_Oneof()
{
TestAllTypes message = new TestAllTypes();
var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.OneofStringFieldNumber].Accessor;
Assert.False(accessor.HasValue(message));
// Even though it's the default value, we still have a value.
message.OneofString = "";
Assert.True(accessor.HasValue(message));
message.OneofString = "hello";
Assert.True(accessor.HasValue(message));
message.OneofUint32 = 10;
Assert.False(accessor.HasValue(message));
}
[Test]
public void HasValue_Proto3_Primitive_Optional()
{
var message = new TestProto3Optional();
var accessor = ((IMessage) message).Descriptor.Fields[TestProto3Optional.OptionalInt64FieldNumber].Accessor;
Assert.IsFalse(accessor.HasValue(message));
message.OptionalInt64 = 5L;
Assert.IsTrue(accessor.HasValue(message));
message.ClearOptionalInt64();
Assert.IsFalse(accessor.HasValue(message));
message.OptionalInt64 = 0L;
Assert.IsTrue(accessor.HasValue(message));
}
[Test]
public void HasValue_Proto3_Primitive_NotOptional()
{
IMessage message = SampleMessages.CreateFullTestAllTypes();
var fields = message.Descriptor.Fields;
@ -106,36 +147,63 @@ namespace Google.Protobuf.Reflection
}
[Test]
public void HasValue_Proto3Optional()
public void HasValue_Proto3_Repeated()
{
IMessage message = new TestProto3Optional
{
OptionalInt32 = 0,
LazyNestedMessage = new TestProto3Optional.Types.NestedMessage()
};
var fields = message.Descriptor.Fields;
Assert.IsFalse(fields[TestProto3Optional.OptionalInt64FieldNumber].Accessor.HasValue(message));
Assert.IsFalse(fields[TestProto3Optional.OptionalNestedMessageFieldNumber].Accessor.HasValue(message));
Assert.IsTrue(fields[TestProto3Optional.LazyNestedMessageFieldNumber].Accessor.HasValue(message));
Assert.IsTrue(fields[TestProto3Optional.OptionalInt32FieldNumber].Accessor.HasValue(message));
var message = new TestAllTypes();
var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.RepeatedBoolFieldNumber].Accessor;
Assert.Throws<InvalidOperationException>(() => accessor.HasValue(message));
}
[Test]
public void HasValue()
public void HasValue_Proto2_Primitive()
{
IMessage message = new Proto2.TestAllTypes();
var fields = message.Descriptor.Fields;
var accessor = fields[Proto2.TestAllTypes.OptionalBoolFieldNumber].Accessor;
var message = new Proto2.TestAllTypes();
var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OptionalInt64FieldNumber].Accessor;
Assert.IsFalse(accessor.HasValue(message));
message.OptionalInt64 = 5L;
Assert.IsTrue(accessor.HasValue(message));
message.ClearOptionalInt64();
Assert.IsFalse(accessor.HasValue(message));
message.OptionalInt64 = 0L;
Assert.IsTrue(accessor.HasValue(message));
}
Assert.False(accessor.HasValue(message));
[Test]
public void HasValue_Proto2_Message()
{
var message = new Proto2.TestAllTypes();
var field = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OptionalForeignMessageFieldNumber];
Assert.False(field.Accessor.HasValue(message));
message.OptionalForeignMessage = new Proto2.ForeignMessage();
Assert.True(field.Accessor.HasValue(message));
message.OptionalForeignMessage = null;
Assert.False(field.Accessor.HasValue(message));
}
accessor.SetValue(message, true);
[Test]
public void HasValue_Proto2_Oneof()
{
var message = new Proto2.TestAllTypes();
var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OneofStringFieldNumber].Accessor;
Assert.False(accessor.HasValue(message));
// Even though it's the default value, we still have a value.
message.OneofString = "";
Assert.True(accessor.HasValue(message));
accessor.Clear(message);
message.OneofString = "hello";
Assert.True(accessor.HasValue(message));
message.OneofUint32 = 10;
Assert.False(accessor.HasValue(message));
}
[Test]
public void HasValue_Proto2_Repeated()
{
var message = new Proto2.TestAllTypes();
var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.RepeatedBoolFieldNumber].Accessor;
Assert.Throws<InvalidOperationException>(() => accessor.HasValue(message));
}
[Test]
public void SetValue_SingleFields()
{
@ -262,6 +330,42 @@ namespace Google.Protobuf.Reflection
Assert.Null(message.OptionalNestedMessage);
}
[Test]
public void Clear_Proto3_Oneof()
{
var message = new TestAllTypes();
var accessor = ((IMessage) message).Descriptor.Fields[TestProtos.TestAllTypes.OneofUint32FieldNumber].Accessor;
// The field accessor Clear method only affects a oneof if the current case is the one being cleared.
message.OneofString = "hello";
Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
accessor.Clear(message);
Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
message.OneofUint32 = 100;
Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase);
accessor.Clear(message);
Assert.AreEqual(TestProtos.TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
}
[Test]
public void Clear_Proto2_Oneof()
{
var message = new Proto2.TestAllTypes();
var accessor = ((IMessage) message).Descriptor.Fields[Proto2.TestAllTypes.OneofUint32FieldNumber].Accessor;
// The field accessor Clear method only affects a oneof if the current case is the one being cleared.
message.OneofString = "hello";
Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
accessor.Clear(message);
Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.OneofString, message.OneofFieldCase);
message.OneofUint32 = 100;
Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase);
accessor.Clear(message);
Assert.AreEqual(Proto2.TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase);
}
[Test]
public void FieldDescriptor_ByName()
{
@ -301,5 +405,32 @@ namespace Google.Protobuf.Reflection
message.ClearExtension(RepeatedBoolExtension);
Assert.IsNull(message.GetExtension(RepeatedBoolExtension));
}
[Test]
public void HasPresence()
{
// Proto3
var fields = TestProtos.TestAllTypes.Descriptor.Fields;
Assert.IsFalse(fields[TestProtos.TestAllTypes.SingleBoolFieldNumber].HasPresence);
Assert.IsTrue(fields[TestProtos.TestAllTypes.OneofBytesFieldNumber].HasPresence);
Assert.IsTrue(fields[TestProtos.TestAllTypes.SingleForeignMessageFieldNumber].HasPresence);
Assert.IsFalse(fields[TestProtos.TestAllTypes.RepeatedBoolFieldNumber].HasPresence);
fields = TestMap.Descriptor.Fields;
Assert.IsFalse(fields[TestMap.MapBoolBoolFieldNumber].HasPresence);
fields = TestProto3Optional.Descriptor.Fields;
Assert.IsTrue(fields[TestProto3Optional.OptionalBoolFieldNumber].HasPresence);
// Proto2
fields = Proto2.TestAllTypes.Descriptor.Fields;
Assert.IsTrue(fields[Proto2.TestAllTypes.OptionalBoolFieldNumber].HasPresence);
Assert.IsTrue(fields[Proto2.TestAllTypes.OneofBytesFieldNumber].HasPresence);
Assert.IsTrue(fields[Proto2.TestAllTypes.OptionalForeignMessageFieldNumber].HasPresence);
Assert.IsFalse(fields[Proto2.TestAllTypes.RepeatedBoolFieldNumber].HasPresence);
fields = Proto2.TestRequired.Descriptor.Fields;
Assert.IsTrue(fields[Proto2.TestRequired.AFieldNumber].HasPresence);
}
}
}

@ -55,6 +55,8 @@ namespace Google.Protobuf
/// Gets the field number of this extension
/// </summary>
public int FieldNumber { get; }
internal abstract bool IsRepeated { get; }
}
/// <summary>
@ -79,6 +81,8 @@ namespace Google.Protobuf
internal override Type TargetType => typeof(TTarget);
internal override bool IsRepeated => false;
internal override IExtensionValue CreateValue()
{
return new ExtensionValue<TValue>(codec);
@ -105,6 +109,8 @@ namespace Google.Protobuf
internal override Type TargetType => typeof(TTarget);
internal override bool IsRepeated => true;
internal override IExtensionValue CreateValue()
{
return new RepeatedExtensionValue<TValue>(codec);

@ -352,8 +352,8 @@ namespace Google.Protobuf.Reflection {
enumType_ = other.enumType_.Clone();
service_ = other.service_.Clone();
extension_ = other.extension_.Clone();
options_ = other.HasOptions ? other.options_.Clone() : null;
sourceCodeInfo_ = other.HasSourceCodeInfo ? other.sourceCodeInfo_.Clone() : null;
options_ = other.options_ != null ? other.options_.Clone() : null;
sourceCodeInfo_ = other.sourceCodeInfo_ != null ? other.sourceCodeInfo_.Clone() : null;
syntax_ = other.syntax_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@ -508,16 +508,6 @@ namespace Google.Protobuf.Reflection {
options_ = value;
}
}
/// <summary>Gets whether the options field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasOptions {
get { return options_ != null; }
}
/// <summary>Clears the value of the options field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearOptions() {
options_ = null;
}
/// <summary>Field number for the "source_code_info" field.</summary>
public const int SourceCodeInfoFieldNumber = 9;
@ -535,16 +525,6 @@ namespace Google.Protobuf.Reflection {
sourceCodeInfo_ = value;
}
}
/// <summary>Gets whether the source_code_info field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasSourceCodeInfo {
get { return sourceCodeInfo_ != null; }
}
/// <summary>Clears the value of the source_code_info field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearSourceCodeInfo() {
sourceCodeInfo_ = null;
}
/// <summary>Field number for the "syntax" field.</summary>
public const int SyntaxFieldNumber = 12;
@ -613,8 +593,8 @@ namespace Google.Protobuf.Reflection {
hash ^= enumType_.GetHashCode();
hash ^= service_.GetHashCode();
hash ^= extension_.GetHashCode();
if (HasOptions) hash ^= Options.GetHashCode();
if (HasSourceCodeInfo) hash ^= SourceCodeInfo.GetHashCode();
if (options_ != null) hash ^= Options.GetHashCode();
if (sourceCodeInfo_ != null) hash ^= SourceCodeInfo.GetHashCode();
if (HasSyntax) hash ^= Syntax.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
@ -642,11 +622,11 @@ namespace Google.Protobuf.Reflection {
enumType_.WriteTo(output, _repeated_enumType_codec);
service_.WriteTo(output, _repeated_service_codec);
extension_.WriteTo(output, _repeated_extension_codec);
if (HasOptions) {
if (options_ != null) {
output.WriteRawTag(66);
output.WriteMessage(Options);
}
if (HasSourceCodeInfo) {
if (sourceCodeInfo_ != null) {
output.WriteRawTag(74);
output.WriteMessage(SourceCodeInfo);
}
@ -677,10 +657,10 @@ namespace Google.Protobuf.Reflection {
size += enumType_.CalculateSize(_repeated_enumType_codec);
size += service_.CalculateSize(_repeated_service_codec);
size += extension_.CalculateSize(_repeated_extension_codec);
if (HasOptions) {
if (options_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
}
if (HasSourceCodeInfo) {
if (sourceCodeInfo_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(SourceCodeInfo);
}
if (HasSyntax) {
@ -710,14 +690,14 @@ namespace Google.Protobuf.Reflection {
enumType_.Add(other.enumType_);
service_.Add(other.service_);
extension_.Add(other.extension_);
if (other.HasOptions) {
if (!HasOptions) {
if (other.options_ != null) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.FileOptions();
}
Options.MergeFrom(other.Options);
}
if (other.HasSourceCodeInfo) {
if (!HasSourceCodeInfo) {
if (other.sourceCodeInfo_ != null) {
if (sourceCodeInfo_ == null) {
SourceCodeInfo = new global::Google.Protobuf.Reflection.SourceCodeInfo();
}
SourceCodeInfo.MergeFrom(other.SourceCodeInfo);
@ -765,14 +745,14 @@ namespace Google.Protobuf.Reflection {
break;
}
case 66: {
if (!HasOptions) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.FileOptions();
}
input.ReadMessage(Options);
break;
}
case 74: {
if (!HasSourceCodeInfo) {
if (sourceCodeInfo_ == null) {
SourceCodeInfo = new global::Google.Protobuf.Reflection.SourceCodeInfo();
}
input.ReadMessage(SourceCodeInfo);
@ -833,7 +813,7 @@ namespace Google.Protobuf.Reflection {
enumType_ = other.enumType_.Clone();
extensionRange_ = other.extensionRange_.Clone();
oneofDecl_ = other.oneofDecl_.Clone();
options_ = other.HasOptions ? other.options_.Clone() : null;
options_ = other.options_ != null ? other.options_.Clone() : null;
reservedRange_ = other.reservedRange_.Clone();
reservedName_ = other.reservedName_.Clone();
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@ -937,16 +917,6 @@ namespace Google.Protobuf.Reflection {
options_ = value;
}
}
/// <summary>Gets whether the options field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasOptions {
get { return options_ != null; }
}
/// <summary>Clears the value of the options field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearOptions() {
options_ = null;
}
/// <summary>Field number for the "reserved_range" field.</summary>
public const int ReservedRangeFieldNumber = 9;
@ -1008,7 +978,7 @@ namespace Google.Protobuf.Reflection {
hash ^= enumType_.GetHashCode();
hash ^= extensionRange_.GetHashCode();
hash ^= oneofDecl_.GetHashCode();
if (HasOptions) hash ^= Options.GetHashCode();
if (options_ != null) hash ^= Options.GetHashCode();
hash ^= reservedRange_.GetHashCode();
hash ^= reservedName_.GetHashCode();
if (_unknownFields != null) {
@ -1033,7 +1003,7 @@ namespace Google.Protobuf.Reflection {
enumType_.WriteTo(output, _repeated_enumType_codec);
extensionRange_.WriteTo(output, _repeated_extensionRange_codec);
extension_.WriteTo(output, _repeated_extension_codec);
if (HasOptions) {
if (options_ != null) {
output.WriteRawTag(58);
output.WriteMessage(Options);
}
@ -1057,7 +1027,7 @@ namespace Google.Protobuf.Reflection {
size += enumType_.CalculateSize(_repeated_enumType_codec);
size += extensionRange_.CalculateSize(_repeated_extensionRange_codec);
size += oneofDecl_.CalculateSize(_repeated_oneofDecl_codec);
if (HasOptions) {
if (options_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
}
size += reservedRange_.CalculateSize(_repeated_reservedRange_codec);
@ -1082,8 +1052,8 @@ namespace Google.Protobuf.Reflection {
enumType_.Add(other.enumType_);
extensionRange_.Add(other.extensionRange_);
oneofDecl_.Add(other.oneofDecl_);
if (other.HasOptions) {
if (!HasOptions) {
if (other.options_ != null) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.MessageOptions();
}
Options.MergeFrom(other.Options);
@ -1126,7 +1096,7 @@ namespace Google.Protobuf.Reflection {
break;
}
case 58: {
if (!HasOptions) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.MessageOptions();
}
input.ReadMessage(Options);
@ -1181,7 +1151,7 @@ namespace Google.Protobuf.Reflection {
_hasBits0 = other._hasBits0;
start_ = other.start_;
end_ = other.end_;
options_ = other.HasOptions ? other.options_.Clone() : null;
options_ = other.options_ != null ? other.options_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@ -1254,16 +1224,6 @@ namespace Google.Protobuf.Reflection {
options_ = value;
}
}
/// <summary>Gets whether the options field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasOptions {
get { return options_ != null; }
}
/// <summary>Clears the value of the options field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearOptions() {
options_ = null;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
@ -1289,7 +1249,7 @@ namespace Google.Protobuf.Reflection {
int hash = 1;
if (HasStart) hash ^= Start.GetHashCode();
if (HasEnd) hash ^= End.GetHashCode();
if (HasOptions) hash ^= Options.GetHashCode();
if (options_ != null) hash ^= Options.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
@ -1311,7 +1271,7 @@ namespace Google.Protobuf.Reflection {
output.WriteRawTag(16);
output.WriteInt32(End);
}
if (HasOptions) {
if (options_ != null) {
output.WriteRawTag(26);
output.WriteMessage(Options);
}
@ -1329,7 +1289,7 @@ namespace Google.Protobuf.Reflection {
if (HasEnd) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(End);
}
if (HasOptions) {
if (options_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
}
if (_unknownFields != null) {
@ -1349,8 +1309,8 @@ namespace Google.Protobuf.Reflection {
if (other.HasEnd) {
End = other.End;
}
if (other.HasOptions) {
if (!HasOptions) {
if (other.options_ != null) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.ExtensionRangeOptions();
}
Options.MergeFrom(other.Options);
@ -1375,7 +1335,7 @@ namespace Google.Protobuf.Reflection {
break;
}
case 26: {
if (!HasOptions) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.ExtensionRangeOptions();
}
input.ReadMessage(Options);
@ -1791,7 +1751,7 @@ namespace Google.Protobuf.Reflection {
defaultValue_ = other.defaultValue_;
oneofIndex_ = other.oneofIndex_;
jsonName_ = other.jsonName_;
options_ = other.HasOptions ? other.options_.Clone() : null;
options_ = other.options_ != null ? other.options_.Clone() : null;
proto3Optional_ = other.proto3Optional_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@ -2054,16 +2014,6 @@ namespace Google.Protobuf.Reflection {
options_ = value;
}
}
/// <summary>Gets whether the options field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasOptions {
get { return options_ != null; }
}
/// <summary>Clears the value of the options field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearOptions() {
options_ = null;
}
/// <summary>Field number for the "proto3_optional" field.</summary>
public const int Proto3OptionalFieldNumber = 17;
@ -2151,7 +2101,7 @@ namespace Google.Protobuf.Reflection {
if (HasDefaultValue) hash ^= DefaultValue.GetHashCode();
if (HasOneofIndex) hash ^= OneofIndex.GetHashCode();
if (HasJsonName) hash ^= JsonName.GetHashCode();
if (HasOptions) hash ^= Options.GetHashCode();
if (options_ != null) hash ^= Options.GetHashCode();
if (HasProto3Optional) hash ^= Proto3Optional.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
@ -2194,7 +2144,7 @@ namespace Google.Protobuf.Reflection {
output.WriteRawTag(58);
output.WriteString(DefaultValue);
}
if (HasOptions) {
if (options_ != null) {
output.WriteRawTag(66);
output.WriteMessage(Options);
}
@ -2245,7 +2195,7 @@ namespace Google.Protobuf.Reflection {
if (HasJsonName) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(JsonName);
}
if (HasOptions) {
if (options_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
}
if (HasProto3Optional) {
@ -2289,8 +2239,8 @@ namespace Google.Protobuf.Reflection {
if (other.HasJsonName) {
JsonName = other.JsonName;
}
if (other.HasOptions) {
if (!HasOptions) {
if (other.options_ != null) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.FieldOptions();
}
Options.MergeFrom(other.Options);
@ -2338,7 +2288,7 @@ namespace Google.Protobuf.Reflection {
break;
}
case 66: {
if (!HasOptions) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.FieldOptions();
}
input.ReadMessage(Options);
@ -2458,7 +2408,7 @@ namespace Google.Protobuf.Reflection {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public OneofDescriptorProto(OneofDescriptorProto other) : this() {
name_ = other.name_;
options_ = other.HasOptions ? other.options_.Clone() : null;
options_ = other.options_ != null ? other.options_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@ -2500,16 +2450,6 @@ namespace Google.Protobuf.Reflection {
options_ = value;
}
}
/// <summary>Gets whether the options field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasOptions {
get { return options_ != null; }
}
/// <summary>Clears the value of the options field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearOptions() {
options_ = null;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
@ -2533,7 +2473,7 @@ namespace Google.Protobuf.Reflection {
public override int GetHashCode() {
int hash = 1;
if (HasName) hash ^= Name.GetHashCode();
if (HasOptions) hash ^= Options.GetHashCode();
if (options_ != null) hash ^= Options.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
@ -2551,7 +2491,7 @@ namespace Google.Protobuf.Reflection {
output.WriteRawTag(10);
output.WriteString(Name);
}
if (HasOptions) {
if (options_ != null) {
output.WriteRawTag(18);
output.WriteMessage(Options);
}
@ -2566,7 +2506,7 @@ namespace Google.Protobuf.Reflection {
if (HasName) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
if (HasOptions) {
if (options_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
}
if (_unknownFields != null) {
@ -2583,8 +2523,8 @@ namespace Google.Protobuf.Reflection {
if (other.HasName) {
Name = other.Name;
}
if (other.HasOptions) {
if (!HasOptions) {
if (other.options_ != null) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.OneofOptions();
}
Options.MergeFrom(other.Options);
@ -2605,7 +2545,7 @@ namespace Google.Protobuf.Reflection {
break;
}
case 18: {
if (!HasOptions) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.OneofOptions();
}
input.ReadMessage(Options);
@ -2647,7 +2587,7 @@ namespace Google.Protobuf.Reflection {
public EnumDescriptorProto(EnumDescriptorProto other) : this() {
name_ = other.name_;
value_ = other.value_.Clone();
options_ = other.HasOptions ? other.options_.Clone() : null;
options_ = other.options_ != null ? other.options_.Clone() : null;
reservedRange_ = other.reservedRange_.Clone();
reservedName_ = other.reservedName_.Clone();
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@ -2701,16 +2641,6 @@ namespace Google.Protobuf.Reflection {
options_ = value;
}
}
/// <summary>Gets whether the options field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasOptions {
get { return options_ != null; }
}
/// <summary>Clears the value of the options field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearOptions() {
options_ = null;
}
/// <summary>Field number for the "reserved_range" field.</summary>
public const int ReservedRangeFieldNumber = 4;
@ -2767,7 +2697,7 @@ namespace Google.Protobuf.Reflection {
int hash = 1;
if (HasName) hash ^= Name.GetHashCode();
hash ^= value_.GetHashCode();
if (HasOptions) hash ^= Options.GetHashCode();
if (options_ != null) hash ^= Options.GetHashCode();
hash ^= reservedRange_.GetHashCode();
hash ^= reservedName_.GetHashCode();
if (_unknownFields != null) {
@ -2788,7 +2718,7 @@ namespace Google.Protobuf.Reflection {
output.WriteString(Name);
}
value_.WriteTo(output, _repeated_value_codec);
if (HasOptions) {
if (options_ != null) {
output.WriteRawTag(26);
output.WriteMessage(Options);
}
@ -2806,7 +2736,7 @@ namespace Google.Protobuf.Reflection {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
size += value_.CalculateSize(_repeated_value_codec);
if (HasOptions) {
if (options_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
}
size += reservedRange_.CalculateSize(_repeated_reservedRange_codec);
@ -2826,8 +2756,8 @@ namespace Google.Protobuf.Reflection {
Name = other.Name;
}
value_.Add(other.value_);
if (other.HasOptions) {
if (!HasOptions) {
if (other.options_ != null) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.EnumOptions();
}
Options.MergeFrom(other.Options);
@ -2854,7 +2784,7 @@ namespace Google.Protobuf.Reflection {
break;
}
case 26: {
if (!HasOptions) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.EnumOptions();
}
input.ReadMessage(Options);
@ -3112,7 +3042,7 @@ namespace Google.Protobuf.Reflection {
_hasBits0 = other._hasBits0;
name_ = other.name_;
number_ = other.number_;
options_ = other.HasOptions ? other.options_.Clone() : null;
options_ = other.options_ != null ? other.options_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@ -3178,16 +3108,6 @@ namespace Google.Protobuf.Reflection {
options_ = value;
}
}
/// <summary>Gets whether the options field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasOptions {
get { return options_ != null; }
}
/// <summary>Clears the value of the options field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearOptions() {
options_ = null;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
@ -3213,7 +3133,7 @@ namespace Google.Protobuf.Reflection {
int hash = 1;
if (HasName) hash ^= Name.GetHashCode();
if (HasNumber) hash ^= Number.GetHashCode();
if (HasOptions) hash ^= Options.GetHashCode();
if (options_ != null) hash ^= Options.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
@ -3235,7 +3155,7 @@ namespace Google.Protobuf.Reflection {
output.WriteRawTag(16);
output.WriteInt32(Number);
}
if (HasOptions) {
if (options_ != null) {
output.WriteRawTag(26);
output.WriteMessage(Options);
}
@ -3253,7 +3173,7 @@ namespace Google.Protobuf.Reflection {
if (HasNumber) {
size += 1 + pb::CodedOutputStream.ComputeInt32Size(Number);
}
if (HasOptions) {
if (options_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
}
if (_unknownFields != null) {
@ -3273,8 +3193,8 @@ namespace Google.Protobuf.Reflection {
if (other.HasNumber) {
Number = other.Number;
}
if (other.HasOptions) {
if (!HasOptions) {
if (other.options_ != null) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.EnumValueOptions();
}
Options.MergeFrom(other.Options);
@ -3299,7 +3219,7 @@ namespace Google.Protobuf.Reflection {
break;
}
case 26: {
if (!HasOptions) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.EnumValueOptions();
}
input.ReadMessage(Options);
@ -3341,7 +3261,7 @@ namespace Google.Protobuf.Reflection {
public ServiceDescriptorProto(ServiceDescriptorProto other) : this() {
name_ = other.name_;
method_ = other.method_.Clone();
options_ = other.HasOptions ? other.options_.Clone() : null;
options_ = other.options_ != null ? other.options_.Clone() : null;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
}
@ -3393,16 +3313,6 @@ namespace Google.Protobuf.Reflection {
options_ = value;
}
}
/// <summary>Gets whether the options field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasOptions {
get { return options_ != null; }
}
/// <summary>Clears the value of the options field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearOptions() {
options_ = null;
}
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public override bool Equals(object other) {
@ -3428,7 +3338,7 @@ namespace Google.Protobuf.Reflection {
int hash = 1;
if (HasName) hash ^= Name.GetHashCode();
hash ^= method_.GetHashCode();
if (HasOptions) hash ^= Options.GetHashCode();
if (options_ != null) hash ^= Options.GetHashCode();
if (_unknownFields != null) {
hash ^= _unknownFields.GetHashCode();
}
@ -3447,7 +3357,7 @@ namespace Google.Protobuf.Reflection {
output.WriteString(Name);
}
method_.WriteTo(output, _repeated_method_codec);
if (HasOptions) {
if (options_ != null) {
output.WriteRawTag(26);
output.WriteMessage(Options);
}
@ -3463,7 +3373,7 @@ namespace Google.Protobuf.Reflection {
size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
}
size += method_.CalculateSize(_repeated_method_codec);
if (HasOptions) {
if (options_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
}
if (_unknownFields != null) {
@ -3481,8 +3391,8 @@ namespace Google.Protobuf.Reflection {
Name = other.Name;
}
method_.Add(other.method_);
if (other.HasOptions) {
if (!HasOptions) {
if (other.options_ != null) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.ServiceOptions();
}
Options.MergeFrom(other.Options);
@ -3507,7 +3417,7 @@ namespace Google.Protobuf.Reflection {
break;
}
case 26: {
if (!HasOptions) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.ServiceOptions();
}
input.ReadMessage(Options);
@ -3552,7 +3462,7 @@ namespace Google.Protobuf.Reflection {
name_ = other.name_;
inputType_ = other.inputType_;
outputType_ = other.outputType_;
options_ = other.HasOptions ? other.options_.Clone() : null;
options_ = other.options_ != null ? other.options_.Clone() : null;
clientStreaming_ = other.clientStreaming_;
serverStreaming_ = other.serverStreaming_;
_unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
@ -3646,16 +3556,6 @@ namespace Google.Protobuf.Reflection {
options_ = value;
}
}
/// <summary>Gets whether the options field is set</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public bool HasOptions {
get { return options_ != null; }
}
/// <summary>Clears the value of the options field</summary>
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void ClearOptions() {
options_ = null;
}
/// <summary>Field number for the "client_streaming" field.</summary>
public const int ClientStreamingFieldNumber = 5;
@ -3739,7 +3639,7 @@ namespace Google.Protobuf.Reflection {
if (HasName) hash ^= Name.GetHashCode();
if (HasInputType) hash ^= InputType.GetHashCode();
if (HasOutputType) hash ^= OutputType.GetHashCode();
if (HasOptions) hash ^= Options.GetHashCode();
if (options_ != null) hash ^= Options.GetHashCode();
if (HasClientStreaming) hash ^= ClientStreaming.GetHashCode();
if (HasServerStreaming) hash ^= ServerStreaming.GetHashCode();
if (_unknownFields != null) {
@ -3767,7 +3667,7 @@ namespace Google.Protobuf.Reflection {
output.WriteRawTag(26);
output.WriteString(OutputType);
}
if (HasOptions) {
if (options_ != null) {
output.WriteRawTag(34);
output.WriteMessage(Options);
}
@ -3796,7 +3696,7 @@ namespace Google.Protobuf.Reflection {
if (HasOutputType) {
size += 1 + pb::CodedOutputStream.ComputeStringSize(OutputType);
}
if (HasOptions) {
if (options_ != null) {
size += 1 + pb::CodedOutputStream.ComputeMessageSize(Options);
}
if (HasClientStreaming) {
@ -3825,8 +3725,8 @@ namespace Google.Protobuf.Reflection {
if (other.HasOutputType) {
OutputType = other.OutputType;
}
if (other.HasOptions) {
if (!HasOptions) {
if (other.options_ != null) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.MethodOptions();
}
Options.MergeFrom(other.Options);
@ -3861,7 +3761,7 @@ namespace Google.Protobuf.Reflection {
break;
}
case 34: {
if (!HasOptions) {
if (options_ == null) {
Options = new global::Google.Protobuf.Reflection.MethodOptions();
}
input.ReadMessage(Options);

@ -128,12 +128,21 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this enum.
/// </summary>
[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
/// <summary>
/// The <c>EnumOptions</c>, defined in <c>descriptor.proto</c>.
/// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
/// Custom options can be retrieved as extensions of the returned message.
/// NOTE: A defensive copy is created each time this property is retrieved.
/// </summary>
public EnumOptions GetOptions() => Proto.Options?.Clone();
/// <summary>
/// Gets a single value enum option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public T GetOption<T>(Extension<EnumOptions, T> extension)
{
var value = Proto.Options.GetExtension(extension);
@ -143,6 +152,7 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// Gets a repeated value enum option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public RepeatedField<T> GetOption<T>(RepeatedExtension<EnumOptions, T> extension)
{
return Proto.Options.GetExtension(extension).Clone();

@ -73,12 +73,21 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this enum value.
/// </summary>
[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
/// <summary>
/// The <c>EnumValueOptions</c>, defined in <c>descriptor.proto</c>.
/// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
/// Custom options can be retrieved as extensions of the returned message.
/// NOTE: A defensive copy is created each time this property is retrieved.
/// </summary>
public EnumValueOptions GetOptions() => Proto.Options?.Clone();
/// <summary>
/// Gets a single value enum value option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public T GetOption<T>(Extension<EnumValueOptions, T> extension)
{
var value = Proto.Options.GetExtension(extension);
@ -88,6 +97,7 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// Gets a repeated value enum value option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public RepeatedField<T> GetOption<T>(RepeatedExtension<EnumValueOptions, T> extension)
{
return Proto.Options.GetExtension(extension).Clone();

@ -70,6 +70,21 @@ namespace Google.Protobuf.Reflection
/// </summary>
public string JsonName { get; }
/// <summary>
/// Indicates whether this field supports presence, either implicitly (e.g. due to it being a message
/// type field) or explicitly via Has/Clear members. If this returns true, it is safe to call
/// <see cref="IFieldAccessor.Clear(IMessage)"/> and <see cref="IFieldAccessor.HasValue(IMessage)"/>
/// on this field's accessor with a suitable message.
/// </summary>
public bool HasPresence =>
Extension != null ? !Extension.IsRepeated
: IsRepeated ? false
: IsMap ? false
: FieldType == FieldType.Message ? true
// This covers "real oneof members" and "proto3 optional fields"
: ContainingOneof != null ? true
: File.Syntax == Syntax.Proto2;
internal FieldDescriptorProto Proto { get; }
/// <summary>
@ -304,12 +319,21 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this field.
/// </summary>
[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
/// <summary>
/// The <c>FieldOptions</c>, defined in <c>descriptor.proto</c>.
/// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
/// Custom options can be retrieved as extensions of the returned message.
/// NOTE: A defensive copy is created each time this property is retrieved.
/// </summary>
public FieldOptions GetOptions() => Proto.Options?.Clone();
/// <summary>
/// Gets a single value field option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public T GetOption<T>(Extension<FieldOptions, T> extension)
{
var value = Proto.Options.GetExtension(extension);
@ -319,6 +343,7 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// Gets a repeated value field option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public RepeatedField<T> GetOption<T>(RepeatedExtension<FieldOptions, T> extension)
{
return Proto.Options.GetExtension(extension).Clone();
@ -394,7 +419,7 @@ namespace Google.Protobuf.Reflection
File.DescriptorPool.AddFieldByNumber(this);
if (ContainingType != null && ContainingType.Proto.HasOptions && ContainingType.Proto.Options.MessageSetWireFormat)
if (ContainingType != null && ContainingType.Proto.Options != null && ContainingType.Proto.Options.MessageSetWireFormat)
{
throw new DescriptorValidationException(this, "MessageSet format is not supported.");
}

@ -547,12 +547,21 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this file.
/// </summary>
[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
/// <summary>
/// The <c>FileOptions</c>, defined in <c>descriptor.proto</c>.
/// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
/// Custom options can be retrieved as extensions of the returned message.
/// NOTE: A defensive copy is created each time this property is retrieved.
/// </summary>
public FileOptions GetOptions() => Proto.Options?.Clone();
/// <summary>
/// Gets a single value file option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public T GetOption<T>(Extension<FileOptions, T> extension)
{
var value = Proto.Options.GetExtension(extension);
@ -562,6 +571,7 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// Gets a repeated value file option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public RepeatedField<T> GetOption<T>(RepeatedExtension<FileOptions, T> extension)
{
return Proto.Options.GetExtension(extension).Clone();

@ -287,12 +287,21 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this message.
/// </summary>
[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
/// <summary>
/// The <c>MessageOptions</c>, defined in <c>descriptor.proto</c>.
/// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
/// Custom options can be retrieved as extensions of the returned message.
/// NOTE: A defensive copy is created each time this property is retrieved.
/// </summary>
public MessageOptions GetOptions() => Proto.Options?.Clone();
/// <summary>
/// Gets a single value message option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public T GetOption<T>(Extension<MessageOptions, T> extension)
{
var value = Proto.Options.GetExtension(extension);
@ -302,6 +311,7 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// Gets a repeated value message option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public Collections.RepeatedField<T> GetOption<T>(RepeatedExtension<MessageOptions, T> extension)
{
return Proto.Options.GetExtension(extension).Clone();

@ -73,12 +73,21 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this method.
/// </summary>
[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
/// <summary>
/// The <c>MethodOptions</c>, defined in <c>descriptor.proto</c>.
/// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
/// Custom options can be retrieved as extensions of the returned message.
/// NOTE: A defensive copy is created each time this property is retrieved.
/// </summary>
public MethodOptions GetOptions() => Proto.Options?.Clone();
/// <summary>
/// Gets a single value method option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public T GetOption<T>(Extension<MethodOptions, T> extension)
{
var value = Proto.Options.GetExtension(extension);
@ -88,6 +97,7 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// Gets a repeated value method option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public RepeatedField<T> GetOption<T>(RepeatedExtension<MethodOptions, T> extension)
{
return Proto.Options.GetExtension(extension).Clone();

@ -117,12 +117,21 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this oneof.
/// </summary>
[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use the GetOptions method.")]
public CustomOptions CustomOptions => new CustomOptions(proto.Options?._extensions?.ValuesByNumber);
/// <summary>
/// The <c>OneofOptions</c>, defined in <c>descriptor.proto</c>.
/// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
/// Custom options can be retrieved as extensions of the returned message.
/// NOTE: A defensive copy is created each time this property is retrieved.
/// </summary>
public OneofOptions GetOptions() => proto.Options?.Clone();
/// <summary>
/// Gets a single value oneof option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public T GetOption<T>(Extension<OneofOptions, T> extension)
{
var value = proto.Options.GetExtension(extension);
@ -132,6 +141,7 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// Gets a repeated value oneof option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public RepeatedField<T> GetOption<T>(RepeatedExtension<OneofOptions, T> extension)
{
return proto.Options.GetExtension(extension).Clone();

@ -94,12 +94,21 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// The (possibly empty) set of custom options for this service.
/// </summary>
[Obsolete("CustomOptions are obsolete. Use GetOption")]
[Obsolete("CustomOptions are obsolete. Use the GetOptions() method.")]
public CustomOptions CustomOptions => new CustomOptions(Proto.Options?._extensions?.ValuesByNumber);
/// <summary>
/// The <c>ServiceOptions</c>, defined in <c>descriptor.proto</c>.
/// If the options message is not present (i.e. there are no options), <c>null</c> is returned.
/// Custom options can be retrieved as extensions of the returned message.
/// NOTE: A defensive copy is created each time this property is retrieved.
/// </summary>
public ServiceOptions GetOptions() => Proto.Options?.Clone();
/// <summary>
/// Gets a single value service option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public T GetOption<T>(Extension<ServiceOptions, T> extension)
{
var value = Proto.Options.GetExtension(extension);
@ -109,6 +118,7 @@ namespace Google.Protobuf.Reflection
/// <summary>
/// Gets a repeated value service option for this descriptor
/// </summary>
[Obsolete("GetOption is obsolete. Use the GetOptions() method.")]
public RepeatedField<T> GetOption<T>(RepeatedExtension<ServiceOptions, T> extension)
{
return Proto.Options.GetExtension(extension).Clone();

@ -57,63 +57,68 @@ namespace Google.Protobuf.Reflection
throw new ArgumentException("Not all required properties/methods available");
}
setValueDelegate = ReflectionUtil.CreateActionIMessageObject(property.GetSetMethod());
if (descriptor.File.Syntax == Syntax.Proto3 && !descriptor.Proto.Proto3Optional)
// Note: this looks worrying in that we access the containing oneof, which isn't valid until cross-linking
// is complete... but field accessors aren't created until after cross-linking.
// The oneof itself won't be cross-linked yet, but that's okay: the oneof accessor is created
// earlier.
// Message fields always support presence, via null checks.
if (descriptor.FieldType == FieldType.Message)
{
hasDelegate = message => GetValue(message) != null;
clearDelegate = message => SetValue(message, null);
}
// Oneof fields always support presence, via case checks.
// Note that clearing the field is a no-op unless that specific field is the current "case".
else if (descriptor.RealContainingOneof != null)
{
hasDelegate = message =>
var oneofAccessor = descriptor.RealContainingOneof.Accessor;
hasDelegate = message => oneofAccessor.GetCaseFieldDescriptor(message) == descriptor;
clearDelegate = message =>
{
throw new InvalidOperationException("HasValue is not implemented for non-optional proto3 fields");
// Clear on a field only affects the oneof itself if the current case is the field we're accessing.
if (oneofAccessor.GetCaseFieldDescriptor(message) == descriptor)
{
oneofAccessor.Clear(message);
}
};
var clrType = property.PropertyType;
// TODO: Validate that this is a reasonable single field? (Should be a value type, a message type, or string/ByteString.)
object defaultValue =
descriptor.FieldType == FieldType.Message ? null
: clrType == typeof(string) ? ""
: clrType == typeof(ByteString) ? ByteString.Empty
: Activator.CreateInstance(clrType);
clearDelegate = message => SetValue(message, defaultValue);
}
else
// Primitive fields always support presence in proto2, and support presence in proto3 for optional fields.
else if (descriptor.File.Syntax == Syntax.Proto2 || descriptor.Proto.Proto3Optional)
{
// For message fields, just compare with null and set to null.
// For primitive fields, use the Has/Clear methods.
if (descriptor.FieldType == FieldType.Message)
MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod;
if (hasMethod == null)
{
hasDelegate = message => GetValue(message) != null;
clearDelegate = message => SetValue(message, null);
throw new ArgumentException("Not all required properties/methods are available");
}
else
hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod);
MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes);
if (clearMethod == null)
{
MethodInfo hasMethod = property.DeclaringType.GetRuntimeProperty("Has" + property.Name).GetMethod;
if (hasMethod == null)
{
throw new ArgumentException("Not all required properties/methods are available");
}
hasDelegate = ReflectionUtil.CreateFuncIMessageBool(hasMethod);
MethodInfo clearMethod = property.DeclaringType.GetRuntimeMethod("Clear" + property.Name, ReflectionUtil.EmptyTypes);
if (clearMethod == null)
{
throw new ArgumentException("Not all required properties/methods are available");
}
clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod);
throw new ArgumentException("Not all required properties/methods are available");
}
clearDelegate = ReflectionUtil.CreateActionIMessage(clearMethod);
}
}
// What's left?
// Primitive proto3 fields without the optional keyword, which aren't in oneofs.
else
{
hasDelegate = message => { throw new InvalidOperationException("Presence is not implemented for this field"); };
public override void Clear(IMessage message)
{
clearDelegate(message);
}
// While presence isn't supported, clearing still is; it's just setting to a default value.
var clrType = property.PropertyType;
public override bool HasValue(IMessage message)
{
return hasDelegate(message);
object defaultValue =
clrType == typeof(string) ? ""
: clrType == typeof(ByteString) ? ByteString.Empty
: Activator.CreateInstance(clrType);
clearDelegate = message => SetValue(message, defaultValue);
}
}
public override void SetValue(IMessage message, object value)
{
setValueDelegate(message, value);
}
public override void Clear(IMessage message) => clearDelegate(message);
public override bool HasValue(IMessage message) => hasDelegate(message);
public override void SetValue(IMessage message, object value) => setValueDelegate(message, value);
}
}

@ -17,6 +17,7 @@
<arg value="${protobuf.source.dir}/google/protobuf/unittest_no_generic_services.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_optimize_for.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3_optional.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_well_known_types.proto"/>
<arg value="${test.proto.dir}/com/google/protobuf/any_test.proto"/>
<arg value="${test.proto.dir}/com/google/protobuf/cached_field_size_test.proto"/>

@ -38,6 +38,7 @@ import com.google.protobuf.Descriptors.OneofDescriptor;
import com.google.protobuf.FieldPresenceTestProto.TestAllTypes;
import com.google.protobuf.FieldPresenceTestProto.TestOptionalFieldsOnly;
import com.google.protobuf.FieldPresenceTestProto.TestRepeatedFieldsOnly;
import com.google.protobuf.testing.proto.TestProto3Optional;
import protobuf_unittest.UnittestProto;
import junit.framework.TestCase;
@ -101,6 +102,113 @@ public class FieldPresenceTest extends TestCase {
UnittestProto.TestAllTypes.Builder.class, TestAllTypes.Builder.class, "OneofBytes");
}
public void testHasMethodForProto3Optional() throws Exception {
assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalInt32());
assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalInt64());
assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalUint32());
assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalUint64());
assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalSint32());
assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalSint64());
assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalFixed32());
assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalFixed64());
assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalFloat());
assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalDouble());
assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalBool());
assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalString());
assertFalse(TestProto3Optional.getDefaultInstance().hasOptionalBytes());
TestProto3Optional.Builder builder = TestProto3Optional.newBuilder().setOptionalInt32(0);
assertTrue(builder.hasOptionalInt32());
assertTrue(builder.build().hasOptionalInt32());
TestProto3Optional.Builder otherBuilder = TestProto3Optional.newBuilder().setOptionalInt32(1);
otherBuilder.mergeFrom(builder.build());
assertTrue(otherBuilder.hasOptionalInt32());
assertEquals(0, otherBuilder.getOptionalInt32());
TestProto3Optional.Builder builder3 =
TestProto3Optional.newBuilder().setOptionalNestedEnumValue(5);
assertTrue(builder3.hasOptionalNestedEnum());
TestProto3Optional.Builder builder4 =
TestProto3Optional.newBuilder().setOptionalNestedEnum(TestProto3Optional.NestedEnum.FOO);
assertTrue(builder4.hasOptionalNestedEnum());
TestProto3Optional proto = TestProto3Optional.parseFrom(builder.build().toByteArray());
assertTrue(proto.hasOptionalInt32());
assertTrue(proto.toBuilder().hasOptionalInt32());
}
private static void assertProto3OptionalReflection(String name) throws Exception {
FieldDescriptor fieldDescriptor = TestProto3Optional.getDescriptor().findFieldByName(name);
OneofDescriptor oneofDescriptor = fieldDescriptor.getContainingOneof();
assertNotNull(fieldDescriptor.getContainingOneof());
assertTrue(fieldDescriptor.hasOptionalKeyword());
assertTrue(fieldDescriptor.hasPresence());
assertFalse(TestProto3Optional.getDefaultInstance().hasOneof(oneofDescriptor));
assertNull(TestProto3Optional.getDefaultInstance().getOneofFieldDescriptor(oneofDescriptor));
TestProto3Optional.Builder builder = TestProto3Optional.newBuilder();
builder.setField(fieldDescriptor, fieldDescriptor.getDefaultValue());
assertTrue(builder.hasField(fieldDescriptor));
assertEquals(fieldDescriptor.getDefaultValue(), builder.getField(fieldDescriptor));
assertTrue(builder.build().hasField(fieldDescriptor));
assertEquals(fieldDescriptor.getDefaultValue(), builder.build().getField(fieldDescriptor));
assertTrue(builder.hasOneof(oneofDescriptor));
assertEquals(fieldDescriptor, builder.getOneofFieldDescriptor(oneofDescriptor));
assertTrue(builder.build().hasOneof(oneofDescriptor));
assertEquals(fieldDescriptor, builder.build().getOneofFieldDescriptor(oneofDescriptor));
TestProto3Optional.Builder otherBuilder = TestProto3Optional.newBuilder();
otherBuilder.mergeFrom(builder.build());
assertTrue(otherBuilder.hasField(fieldDescriptor));
assertEquals(fieldDescriptor.getDefaultValue(), otherBuilder.getField(fieldDescriptor));
TestProto3Optional proto = TestProto3Optional.parseFrom(builder.build().toByteArray());
assertTrue(proto.hasField(fieldDescriptor));
assertTrue(proto.toBuilder().hasField(fieldDescriptor));
DynamicMessage.Builder dynamicBuilder =
DynamicMessage.newBuilder(TestProto3Optional.getDescriptor());
dynamicBuilder.setField(fieldDescriptor, fieldDescriptor.getDefaultValue());
assertTrue(dynamicBuilder.hasField(fieldDescriptor));
assertEquals(fieldDescriptor.getDefaultValue(), dynamicBuilder.getField(fieldDescriptor));
assertTrue(dynamicBuilder.build().hasField(fieldDescriptor));
assertEquals(
fieldDescriptor.getDefaultValue(), dynamicBuilder.build().getField(fieldDescriptor));
assertTrue(dynamicBuilder.hasOneof(oneofDescriptor));
assertEquals(fieldDescriptor, dynamicBuilder.getOneofFieldDescriptor(oneofDescriptor));
assertTrue(dynamicBuilder.build().hasOneof(oneofDescriptor));
assertEquals(fieldDescriptor, dynamicBuilder.build().getOneofFieldDescriptor(oneofDescriptor));
DynamicMessage.Builder otherDynamicBuilder =
DynamicMessage.newBuilder(TestProto3Optional.getDescriptor());
otherDynamicBuilder.mergeFrom(dynamicBuilder.build());
assertTrue(otherDynamicBuilder.hasField(fieldDescriptor));
assertEquals(fieldDescriptor.getDefaultValue(), otherDynamicBuilder.getField(fieldDescriptor));
DynamicMessage dynamicProto =
DynamicMessage.parseFrom(TestProto3Optional.getDescriptor(), builder.build().toByteArray());
assertTrue(dynamicProto.hasField(fieldDescriptor));
assertTrue(dynamicProto.toBuilder().hasField(fieldDescriptor));
}
public void testProto3Optional_reflection() throws Exception {
assertProto3OptionalReflection("optional_int32");
assertProto3OptionalReflection("optional_int64");
assertProto3OptionalReflection("optional_uint32");
assertProto3OptionalReflection("optional_uint64");
assertProto3OptionalReflection("optional_sint32");
assertProto3OptionalReflection("optional_sint64");
assertProto3OptionalReflection("optional_fixed32");
assertProto3OptionalReflection("optional_fixed64");
assertProto3OptionalReflection("optional_float");
assertProto3OptionalReflection("optional_double");
assertProto3OptionalReflection("optional_bool");
assertProto3OptionalReflection("optional_string");
assertProto3OptionalReflection("optional_bytes");
}
public void testOneofEquals() throws Exception {
TestAllTypes.Builder builder = TestAllTypes.newBuilder();

@ -40,6 +40,8 @@ import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.FileDescriptor;
import com.google.protobuf.TextFormat.Parser.SingularOverwritePolicy;
import com.google.protobuf.testing.proto.TestProto3Optional;
import com.google.protobuf.testing.proto.TestProto3Optional.NestedEnum;
import any_test.AnyTestProto.TestAny;
import map_test.MapTestProto.TestMap;
import protobuf_unittest.UnittestMset.TestMessageSetExtension1;
@ -319,6 +321,24 @@ public class TextFormatTest extends TestCase {
assertEquals(canonicalExoticText, message.toString());
}
public void testRoundtripProto3Optional() throws Exception {
Message message =
TestProto3Optional.newBuilder()
.setOptionalInt32(1)
.setOptionalInt64(2)
.setOptionalNestedEnum(NestedEnum.BAZ)
.build();
TestProto3Optional.Builder message2 = TestProto3Optional.newBuilder();
TextFormat.merge(message.toString(), message2);
assertTrue(message2.hasOptionalInt32());
assertTrue(message2.hasOptionalInt64());
assertTrue(message2.hasOptionalNestedEnum());
assertEquals(1, message2.getOptionalInt32());
assertEquals(2, message2.getOptionalInt64());
assertEquals(NestedEnum.BAZ, message2.getOptionalNestedEnum());
}
public void testPrintMessageSet() throws Exception {
TestMessageSet messageSet =
TestMessageSet.newBuilder()

@ -15,6 +15,7 @@
<arg value="${protobuf.source.dir}/google/protobuf/unittest_no_generic_services.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_optimize_for.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_proto3_optional.proto"/>
<arg value="${protobuf.source.dir}/google/protobuf/unittest_well_known_types.proto"/>
<arg value="${protobuf.basedir}/java/core/${test.proto.dir}/com/google/protobuf/any_test.proto"/>
<arg value="${protobuf.basedir}/java/core/${test.proto.dir}/com/google/protobuf/cached_field_size_test.proto"/>

@ -30,10 +30,7 @@
syntax = "proto3";
package protobuf_unittest;
option java_multiple_files = true;
option java_package = "com.google.protobuf.testing.proto";
package google.protobuf.python.internal;
message TestProto3Optional {
message NestedMessage {

@ -159,24 +159,23 @@ inline bool IsProto2(const FileDescriptor* descriptor) {
}
inline bool SupportsPresenceApi(const FieldDescriptor* descriptor) {
// We don't use descriptor->is_singular_with_presence() as C# has slightly
// different behavior to other languages.
if (IsProto2(descriptor->file())) {
// We generate Has/Clear for oneof fields in C#, as well as for messages.
// It's possible that we shouldn't, but stopping doing so would be a
// breaking change for proto2. Fortunately the decision is moot for
// onoeof in proto3: you can't use "optional" inside a oneof.
// Proto2: every singular field has presence. (Even fields in oneofs.)
return !descriptor->is_repeated();
} else {
// Proto3: only for explictly-optional fields that aren't messages.
// (Repeated fields can never be explicitly optional, so we don't need
// to check for that.) Currently we can't get at proto3_optional directly,
// but we can use has_optional_keyword() as a surrogate check.
return descriptor->has_optional_keyword() &&
descriptor->type() != FieldDescriptor::TYPE_MESSAGE;
// 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) {
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();
}
inline bool RequiresPresenceBit(const FieldDescriptor* descriptor) {

@ -225,6 +225,7 @@ void ImmutableEnumFieldGenerator::GenerateBuilderMembers(
printer->Print(variables_,
"$deprecation$public Builder "
"${$set$capitalized_name$Value$}$(int value) {\n"
" $set_has_field_bit_builder$\n"
" $name$_ = value;\n"
" $on_changed$\n"
" return this;\n"

@ -1061,7 +1061,7 @@ void Reflection::ListFields(const Message& message,
if (oneof_case_array[containing_oneof->index()] == field->number()) {
output->push_back(field);
}
} else if (has_bits) {
} else if (has_bits && has_bits_indices[i] != -1) {
// Equivalent to: HasBit(message, field)
if (IsIndexInHasBitSet(has_bits, has_bits_indices[i])) {
output->push_back(field);

@ -217,9 +217,15 @@ TEST(Proto3OptionalTest, OptionalFieldDescriptor) {
for (int i = 0; i < d->field_count(); i++) {
const FieldDescriptor* f = d->field(i);
EXPECT_TRUE(f->has_optional_keyword()) << f->full_name();
EXPECT_TRUE(f->has_presence()) << f->full_name();
EXPECT_TRUE(f->containing_oneof()) << f->full_name();
if (HasPrefixString(f->name(), "singular")) {
EXPECT_FALSE(f->has_optional_keyword()) << f->full_name();
EXPECT_FALSE(f->has_presence()) << f->full_name();
EXPECT_FALSE(f->containing_oneof()) << f->full_name();
} else {
EXPECT_TRUE(f->has_optional_keyword()) << f->full_name();
EXPECT_TRUE(f->has_presence()) << f->full_name();
EXPECT_TRUE(f->containing_oneof()) << f->full_name();
}
}
}

@ -72,4 +72,8 @@ message TestProto3Optional {
optional NestedMessage optional_nested_message = 18;
optional NestedMessage lazy_nested_message = 19 [lazy = true];
optional NestedEnum optional_nested_enum = 21;
// Add some non-optional fields to verify we can mix them.
int32 singular_int32 = 22;
int64 singular_int64 = 23;
}

Loading…
Cancel
Save