Jelajahi Sumber

Implement Clone.

Fixes issue #527.
Jon Skeet 10 tahun lalu
induk
melakukan
6c1fe6ea3e
23 mengubah file dengan 982 tambahan dan 148 penghapusan
  1. 28 6
      csharp/src/AddressBook/Addressbook.cs
  2. 116 8
      csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs
  3. 8 2
      csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs
  4. 8 2
      csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs
  5. 38 8
      csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs
  6. 383 69
      csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs
  7. 1 1
      csharp/src/ProtocolBuffers/ByteString.cs
  8. 30 0
      csharp/src/ProtocolBuffers/Collections/RepeatedField.cs
  9. 257 44
      csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs
  10. 18 0
      csharp/src/ProtocolBuffers/IMessage.cs
  11. 1 0
      src/google/protobuf/compiler/csharp/csharp_field_base.h
  12. 51 8
      src/google/protobuf/compiler/csharp/csharp_message.cc
  13. 1 0
      src/google/protobuf/compiler/csharp/csharp_message.h
  14. 10 0
      src/google/protobuf/compiler/csharp/csharp_message_field.cc
  15. 2 0
      src/google/protobuf/compiler/csharp/csharp_message_field.h
  16. 10 0
      src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
  17. 2 0
      src/google/protobuf/compiler/csharp/csharp_primitive_field.h
  18. 5 0
      src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
  19. 1 0
      src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
  20. 5 0
      src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
  21. 1 0
      src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
  22. 5 0
      src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
  23. 1 0
      src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h

+ 28 - 6
csharp/src/AddressBook/Addressbook.cs

@@ -62,7 +62,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
   }
   #region Messages
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class Person : pb::IMessage<Person>, global::System.IEquatable<Person> {
+  public sealed partial class Person : pb::IMessage<Person>, global::System.IEquatable<Person>, pb::IDeepCloneable<Person> {
     private static readonly pb::MessageParser<Person> _parser = new pb::MessageParser<Person>(() => new Person());
     public static pb::MessageParser<Person> Parser { get { return _parser; } }
 
@@ -77,9 +77,18 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
     }
 
     public Person() { }
+
     public Person(Person other) {
-      MergeFrom(other);
+      name_ = other.name_;
+      id_ = other.id_;
+      email_ = other.email_;
+      phone_ = other.phone_.Clone();
+    }
+
+    public Person Clone() {
+      return new Person(this);
     }
+
     public const int NameFieldNumber = 1;
     private string name_ = "";
     public string Name {
@@ -231,7 +240,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
       }
 
       [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-      public sealed partial class PhoneNumber : pb::IMessage<PhoneNumber>, global::System.IEquatable<PhoneNumber> {
+      public sealed partial class PhoneNumber : pb::IMessage<PhoneNumber>, global::System.IEquatable<PhoneNumber>, pb::IDeepCloneable<PhoneNumber> {
         private static readonly pb::MessageParser<PhoneNumber> _parser = new pb::MessageParser<PhoneNumber>(() => new PhoneNumber());
         public static pb::MessageParser<PhoneNumber> Parser { get { return _parser; } }
 
@@ -246,9 +255,16 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
         }
 
         public PhoneNumber() { }
+
         public PhoneNumber(PhoneNumber other) {
-          MergeFrom(other);
+          number_ = other.number_;
+          type_ = other.type_;
+        }
+
+        public PhoneNumber Clone() {
+          return new PhoneNumber(this);
         }
+
         public const int NumberFieldNumber = 1;
         private string number_ = "";
         public string Number {
@@ -352,7 +368,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class AddressBook : pb::IMessage<AddressBook>, global::System.IEquatable<AddressBook> {
+  public sealed partial class AddressBook : pb::IMessage<AddressBook>, global::System.IEquatable<AddressBook>, pb::IDeepCloneable<AddressBook> {
     private static readonly pb::MessageParser<AddressBook> _parser = new pb::MessageParser<AddressBook>(() => new AddressBook());
     public static pb::MessageParser<AddressBook> Parser { get { return _parser; } }
 
@@ -367,9 +383,15 @@ namespace Google.ProtocolBuffers.Examples.AddressBook {
     }
 
     public AddressBook() { }
+
     public AddressBook(AddressBook other) {
-      MergeFrom(other);
+      person_ = other.person_.Clone();
     }
+
+    public AddressBook Clone() {
+      return new AddressBook(this);
+    }
+
     public const int PersonFieldNumber = 1;
     private readonly pbc::RepeatedField<global::Google.ProtocolBuffers.Examples.AddressBook.Person> person_ = new pbc::RepeatedField<global::Google.ProtocolBuffers.Examples.AddressBook.Person>();
     public pbc::RepeatedField<global::Google.ProtocolBuffers.Examples.AddressBook.Person> Person {

+ 116 - 8
csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs

@@ -1,9 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Google.Protobuf.TestProtos;
+using Google.Protobuf.TestProtos;
 using NUnit.Framework;
 
 namespace Google.Protobuf
@@ -88,7 +83,7 @@ namespace Google.Protobuf
             var message = new TestAllTypes
             {
                 SingleBool = true,
-                SingleBytes = ByteString.CopyFrom(new byte[] { 1, 2, 3, 4 }),
+                SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
                 SingleDouble = 23.5,
                 SingleFixed32 = 23,
                 SingleFixed64 = 1234567890123,
@@ -122,7 +117,7 @@ namespace Google.Protobuf
             var message = new TestAllTypes
             {
                 RepeatedBool = { true, false },
-                RepeatedBytes = { ByteString.CopyFrom(new byte[] { 1, 2, 3, 4 }), ByteString.CopyFrom(new byte[] { 5, 6 }) },
+                RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6) },
                 RepeatedDouble = { -12.25, 23.5 },
                 RepeatedFixed32 = { uint.MaxValue, 23 },
                 RepeatedFixed64 = { ulong.MaxValue, 1234567890123 },
@@ -149,5 +144,118 @@ namespace Google.Protobuf
             TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes);
             Assert.AreEqual(message, parsed);
         }
+
+        [Test]
+        public void CloneSingleNonMessageValues()
+        {
+            var original = new TestAllTypes
+            {
+                SingleBool = true,
+                SingleBytes = ByteString.CopyFrom(1, 2, 3, 4),
+                SingleDouble = 23.5,
+                SingleFixed32 = 23,
+                SingleFixed64 = 1234567890123,
+                SingleFloat = 12.25f,
+                SingleInt32 = 100,
+                SingleInt64 = 3210987654321,
+                SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO,
+                SingleSfixed32 = -123,
+                SingleSfixed64 = -12345678901234,
+                SingleSint32 = -456,
+                SingleSint64 = -12345678901235,
+                SingleString = "test",
+                SingleUint32 = uint.MaxValue,
+                SingleUint64 = ulong.MaxValue
+            };
+            var clone = original.Clone();
+            Assert.AreNotSame(original, clone);
+            Assert.AreEqual(original, clone);
+            // Just as a single example
+            clone.SingleInt32 = 150;
+            Assert.AreNotEqual(original, clone);
+        }
+
+        [Test]
+        public void CloneRepeatedNonMessageValues()
+        {
+            var original = new TestAllTypes
+            {
+                RepeatedBool = { true, false },
+                RepeatedBytes = { ByteString.CopyFrom(1, 2, 3, 4), ByteString.CopyFrom(5, 6) },
+                RepeatedDouble = { -12.25, 23.5 },
+                RepeatedFixed32 = { uint.MaxValue, 23 },
+                RepeatedFixed64 = { ulong.MaxValue, 1234567890123 },
+                RepeatedFloat = { 100f, 12.25f },
+                RepeatedInt32 = { 100, 200 },
+                RepeatedInt64 = { 3210987654321, long.MaxValue },
+                RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.NEG },
+                RepeatedSfixed32 = { -123, 123 },
+                RepeatedSfixed64 = { -12345678901234, 12345678901234 },
+                RepeatedSint32 = { -456, 100 },
+                RepeatedSint64 = { -12345678901235, 123 },
+                RepeatedString = { "foo", "bar" },
+                RepeatedUint32 = { uint.MaxValue, uint.MinValue },
+                RepeatedUint64 = { ulong.MaxValue, uint.MinValue }
+            };
+
+            var clone = original.Clone();
+            Assert.AreNotSame(original, clone);
+            Assert.AreEqual(original, clone);
+            // Just as a single example
+            clone.RepeatedDouble.Add(25.5);
+            Assert.AreNotEqual(original, clone);
+        }
+
+        [Test]
+        public void CloneSingleMessageField()
+        {
+            var original = new TestAllTypes
+            {
+                SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 }
+            };
+
+            var clone = original.Clone();
+            Assert.AreNotSame(original, clone);
+            Assert.AreNotSame(original.SingleNestedMessage, clone.SingleNestedMessage);
+            Assert.AreEqual(original, clone);
+
+            clone.SingleNestedMessage.Bb = 30;
+            Assert.AreNotEqual(original, clone);
+        }
+
+        [Test]
+        public void CloneRepeatedMessageField()
+        {
+            var original = new TestAllTypes
+            {
+                RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 20 } }
+            };
+
+            var clone = original.Clone();
+            Assert.AreNotSame(original, clone);
+            Assert.AreNotSame(original.RepeatedNestedMessage, clone.RepeatedNestedMessage);
+            Assert.AreNotSame(original.RepeatedNestedMessage[0], clone.RepeatedNestedMessage[0]);
+            Assert.AreEqual(original, clone);
+
+            clone.RepeatedNestedMessage[0].Bb = 30;
+            Assert.AreNotEqual(original, clone);
+        }
+
+        [Test]
+        public void CloneOneofField()
+        {
+            var original = new TestAllTypes
+            {
+                OneofNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 20 }
+            };
+
+            var clone = original.Clone();
+            Assert.AreNotSame(original, clone);
+            Assert.AreEqual(original, clone);
+
+            // We should have cloned the message
+            original.OneofNestedMessage.Bb = 30;
+            Assert.AreNotEqual(original, clone);
+        }
     }
 }

+ 8 - 2
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs

@@ -60,7 +60,7 @@ namespace Google.Protobuf.TestProtos {
 
   #region Messages
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class ImportMessage : pb::IMessage<ImportMessage>, global::System.IEquatable<ImportMessage> {
+  public sealed partial class ImportMessage : pb::IMessage<ImportMessage>, global::System.IEquatable<ImportMessage>, pb::IDeepCloneable<ImportMessage> {
     private static readonly pb::MessageParser<ImportMessage> _parser = new pb::MessageParser<ImportMessage>(() => new ImportMessage());
     public static pb::MessageParser<ImportMessage> Parser { get { return _parser; } }
 
@@ -75,9 +75,15 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public ImportMessage() { }
+
     public ImportMessage(ImportMessage other) {
-      MergeFrom(other);
+      d_ = other.d_;
+    }
+
+    public ImportMessage Clone() {
+      return new ImportMessage(this);
     }
+
     public const int DFieldNumber = 1;
     private int d_;
     public int D {

+ 8 - 2
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs

@@ -45,7 +45,7 @@ namespace Google.Protobuf.TestProtos {
   }
   #region Messages
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class PublicImportMessage : pb::IMessage<PublicImportMessage>, global::System.IEquatable<PublicImportMessage> {
+  public sealed partial class PublicImportMessage : pb::IMessage<PublicImportMessage>, global::System.IEquatable<PublicImportMessage>, pb::IDeepCloneable<PublicImportMessage> {
     private static readonly pb::MessageParser<PublicImportMessage> _parser = new pb::MessageParser<PublicImportMessage>(() => new PublicImportMessage());
     public static pb::MessageParser<PublicImportMessage> Parser { get { return _parser; } }
 
@@ -60,9 +60,15 @@ namespace Google.Protobuf.TestProtos {
     }
 
     public PublicImportMessage() { }
+
     public PublicImportMessage(PublicImportMessage other) {
-      MergeFrom(other);
+      e_ = other.e_;
+    }
+
+    public PublicImportMessage Clone() {
+      return new PublicImportMessage(this);
     }
+
     public const int EFieldNumber = 1;
     private int e_;
     public int E {

+ 38 - 8
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs

@@ -90,7 +90,7 @@ namespace UnitTest.Issues.TestProtos {
 
   #region Messages
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class NegativeEnumMessage : pb::IMessage<NegativeEnumMessage>, global::System.IEquatable<NegativeEnumMessage> {
+  public sealed partial class NegativeEnumMessage : pb::IMessage<NegativeEnumMessage>, global::System.IEquatable<NegativeEnumMessage>, pb::IDeepCloneable<NegativeEnumMessage> {
     private static readonly pb::MessageParser<NegativeEnumMessage> _parser = new pb::MessageParser<NegativeEnumMessage>(() => new NegativeEnumMessage());
     public static pb::MessageParser<NegativeEnumMessage> Parser { get { return _parser; } }
 
@@ -105,9 +105,17 @@ namespace UnitTest.Issues.TestProtos {
     }
 
     public NegativeEnumMessage() { }
+
     public NegativeEnumMessage(NegativeEnumMessage other) {
-      MergeFrom(other);
+      value_ = other.value_;
+      values_ = other.values_.Clone();
+      packedValues_ = other.packedValues_.Clone();
+    }
+
+    public NegativeEnumMessage Clone() {
+      return new NegativeEnumMessage(this);
     }
+
     public const int ValueFieldNumber = 1;
     private global::UnitTest.Issues.TestProtos.NegativeEnum value_ = global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO;
     public global::UnitTest.Issues.TestProtos.NegativeEnum Value {
@@ -233,7 +241,7 @@ namespace UnitTest.Issues.TestProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class DeprecatedChild : pb::IMessage<DeprecatedChild>, global::System.IEquatable<DeprecatedChild> {
+  public sealed partial class DeprecatedChild : pb::IMessage<DeprecatedChild>, global::System.IEquatable<DeprecatedChild>, pb::IDeepCloneable<DeprecatedChild> {
     private static readonly pb::MessageParser<DeprecatedChild> _parser = new pb::MessageParser<DeprecatedChild>(() => new DeprecatedChild());
     public static pb::MessageParser<DeprecatedChild> Parser { get { return _parser; } }
 
@@ -248,9 +256,14 @@ namespace UnitTest.Issues.TestProtos {
     }
 
     public DeprecatedChild() { }
+
     public DeprecatedChild(DeprecatedChild other) {
-      MergeFrom(other);
     }
+
+    public DeprecatedChild Clone() {
+      return new DeprecatedChild(this);
+    }
+
     public override bool Equals(object other) {
       return Equals(other as DeprecatedChild);
     }
@@ -301,7 +314,7 @@ namespace UnitTest.Issues.TestProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class DeprecatedFieldsMessage : pb::IMessage<DeprecatedFieldsMessage>, global::System.IEquatable<DeprecatedFieldsMessage> {
+  public sealed partial class DeprecatedFieldsMessage : pb::IMessage<DeprecatedFieldsMessage>, global::System.IEquatable<DeprecatedFieldsMessage>, pb::IDeepCloneable<DeprecatedFieldsMessage> {
     private static readonly pb::MessageParser<DeprecatedFieldsMessage> _parser = new pb::MessageParser<DeprecatedFieldsMessage>(() => new DeprecatedFieldsMessage());
     public static pb::MessageParser<DeprecatedFieldsMessage> Parser { get { return _parser; } }
 
@@ -316,9 +329,20 @@ namespace UnitTest.Issues.TestProtos {
     }
 
     public DeprecatedFieldsMessage() { }
+
     public DeprecatedFieldsMessage(DeprecatedFieldsMessage other) {
-      MergeFrom(other);
+      primitiveValue_ = other.primitiveValue_;
+      primitiveArray_ = other.primitiveArray_.Clone();
+      MessageValue = other.messageValue_ != null ? other.MessageValue.Clone() : null;
+      messageArray_ = other.messageArray_.Clone();
+      enumValue_ = other.enumValue_;
+      enumArray_ = other.enumArray_.Clone();
+    }
+
+    public DeprecatedFieldsMessage Clone() {
+      return new DeprecatedFieldsMessage(this);
     }
+
     public const int PrimitiveValueFieldNumber = 1;
     private int primitiveValue_;
     [global::System.ObsoleteAttribute()]
@@ -525,7 +549,7 @@ namespace UnitTest.Issues.TestProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class ItemField : pb::IMessage<ItemField>, global::System.IEquatable<ItemField> {
+  public sealed partial class ItemField : pb::IMessage<ItemField>, global::System.IEquatable<ItemField>, pb::IDeepCloneable<ItemField> {
     private static readonly pb::MessageParser<ItemField> _parser = new pb::MessageParser<ItemField>(() => new ItemField());
     public static pb::MessageParser<ItemField> Parser { get { return _parser; } }
 
@@ -540,9 +564,15 @@ namespace UnitTest.Issues.TestProtos {
     }
 
     public ItemField() { }
+
     public ItemField(ItemField other) {
-      MergeFrom(other);
+      item_ = other.item_;
+    }
+
+    public ItemField Clone() {
+      return new ItemField(this);
     }
+
     public const int ItemFieldNumber = 1;
     private int item_;
     public int Item {

File diff ditekan karena terlalu besar
+ 383 - 69
csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs


+ 1 - 1
csharp/src/ProtocolBuffers/ByteString.cs

@@ -139,7 +139,7 @@ namespace Google.Protobuf
         /// are copied, so further modifications to the array will not
         /// be reflected in the returned ByteString.
         /// </summary>
-        public static ByteString CopyFrom(byte[] bytes)
+        public static ByteString CopyFrom(params byte[] bytes)
         {
             return new ByteString((byte[]) bytes.Clone());
         }

+ 30 - 0
csharp/src/ProtocolBuffers/Collections/RepeatedField.cs

@@ -12,6 +12,36 @@ namespace Google.Protobuf.Collections
         private T[] array = EmptyArray;
         private int count = 0;
 
+        /// <summary>
+        /// Creates a deep clone of this repeated field.
+        /// </summary>
+        /// <remarks>
+        /// If the field type is
+        /// a message type, each element is also cloned; otherwise, it is
+        /// assumed that the field type is primitive (including string and
+        /// bytes, both of which are immutable) and so a simple copy is
+        /// equivalent to a deep clone.
+        /// </remarks>
+        /// <returns>A deep clone of this repeated field.</returns>
+        public RepeatedField<T> Clone()
+        {
+            RepeatedField<T> clone = new RepeatedField<T>();
+            if (array != EmptyArray)
+            {
+                clone.array = (T[])array.Clone();
+                IDeepCloneable<T>[] cloneableArray = clone.array as IDeepCloneable<T>[];
+                if (cloneableArray != null)
+                {
+                    for (int i = 0; i < count; i++)
+                    {
+                        clone.array[i] = cloneableArray[i].Clone();
+                    }
+                }
+            }
+            clone.count = count;
+            return clone;
+        }
+
         private void EnsureSize(int size)
         {
             size = Math.Max(size, MinArraySize);

+ 257 - 44
csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs

@@ -278,7 +278,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
   #region Messages
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class FileDescriptorSet : pb::IMessage<FileDescriptorSet>, global::System.IEquatable<FileDescriptorSet> {
+  public sealed partial class FileDescriptorSet : pb::IMessage<FileDescriptorSet>, global::System.IEquatable<FileDescriptorSet>, pb::IDeepCloneable<FileDescriptorSet> {
     private static readonly pb::MessageParser<FileDescriptorSet> _parser = new pb::MessageParser<FileDescriptorSet>(() => new FileDescriptorSet());
     public static pb::MessageParser<FileDescriptorSet> Parser { get { return _parser; } }
 
@@ -293,9 +293,15 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public FileDescriptorSet() { }
+
     public FileDescriptorSet(FileDescriptorSet other) {
-      MergeFrom(other);
+      file_ = other.file_.Clone();
+    }
+
+    public FileDescriptorSet Clone() {
+      return new FileDescriptorSet(this);
     }
+
     public const int FileFieldNumber = 1;
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto> file_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto>();
     public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.FileDescriptorProto> File {
@@ -368,7 +374,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class FileDescriptorProto : pb::IMessage<FileDescriptorProto>, global::System.IEquatable<FileDescriptorProto> {
+  public sealed partial class FileDescriptorProto : pb::IMessage<FileDescriptorProto>, global::System.IEquatable<FileDescriptorProto>, pb::IDeepCloneable<FileDescriptorProto> {
     private static readonly pb::MessageParser<FileDescriptorProto> _parser = new pb::MessageParser<FileDescriptorProto>(() => new FileDescriptorProto());
     public static pb::MessageParser<FileDescriptorProto> Parser { get { return _parser; } }
 
@@ -383,9 +389,26 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public FileDescriptorProto() { }
+
     public FileDescriptorProto(FileDescriptorProto other) {
-      MergeFrom(other);
+      name_ = other.name_;
+      package_ = other.package_;
+      dependency_ = other.dependency_.Clone();
+      publicDependency_ = other.publicDependency_.Clone();
+      weakDependency_ = other.weakDependency_.Clone();
+      messageType_ = other.messageType_.Clone();
+      enumType_ = other.enumType_.Clone();
+      service_ = other.service_.Clone();
+      extension_ = other.extension_.Clone();
+      Options = other.options_ != null ? other.Options.Clone() : null;
+      SourceCodeInfo = other.sourceCodeInfo_ != null ? other.SourceCodeInfo.Clone() : null;
+      syntax_ = other.syntax_;
     }
+
+    public FileDescriptorProto Clone() {
+      return new FileDescriptorProto(this);
+    }
+
     public const int NameFieldNumber = 1;
     private string name_ = "";
     public string Name {
@@ -726,7 +749,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class DescriptorProto : pb::IMessage<DescriptorProto>, global::System.IEquatable<DescriptorProto> {
+  public sealed partial class DescriptorProto : pb::IMessage<DescriptorProto>, global::System.IEquatable<DescriptorProto>, pb::IDeepCloneable<DescriptorProto> {
     private static readonly pb::MessageParser<DescriptorProto> _parser = new pb::MessageParser<DescriptorProto>(() => new DescriptorProto());
     public static pb::MessageParser<DescriptorProto> Parser { get { return _parser; } }
 
@@ -741,9 +764,24 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public DescriptorProto() { }
+
     public DescriptorProto(DescriptorProto other) {
-      MergeFrom(other);
+      name_ = other.name_;
+      field_ = other.field_.Clone();
+      extension_ = other.extension_.Clone();
+      nestedType_ = other.nestedType_.Clone();
+      enumType_ = other.enumType_.Clone();
+      extensionRange_ = other.extensionRange_.Clone();
+      oneofDecl_ = other.oneofDecl_.Clone();
+      Options = other.options_ != null ? other.Options.Clone() : null;
+      reservedRange_ = other.reservedRange_.Clone();
+      reservedName_ = other.reservedName_.Clone();
+    }
+
+    public DescriptorProto Clone() {
+      return new DescriptorProto(this);
     }
+
     public const int NameFieldNumber = 1;
     private string name_ = "";
     public string Name {
@@ -1025,7 +1063,7 @@ namespace Google.Protobuf.DescriptorProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Types {
       [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-      public sealed partial class ExtensionRange : pb::IMessage<ExtensionRange>, global::System.IEquatable<ExtensionRange> {
+      public sealed partial class ExtensionRange : pb::IMessage<ExtensionRange>, global::System.IEquatable<ExtensionRange>, pb::IDeepCloneable<ExtensionRange> {
         private static readonly pb::MessageParser<ExtensionRange> _parser = new pb::MessageParser<ExtensionRange>(() => new ExtensionRange());
         public static pb::MessageParser<ExtensionRange> Parser { get { return _parser; } }
 
@@ -1040,9 +1078,16 @@ namespace Google.Protobuf.DescriptorProtos {
         }
 
         public ExtensionRange() { }
+
         public ExtensionRange(ExtensionRange other) {
-          MergeFrom(other);
+          start_ = other.start_;
+          end_ = other.end_;
+        }
+
+        public ExtensionRange Clone() {
+          return new ExtensionRange(this);
         }
+
         public const int StartFieldNumber = 1;
         private int start_;
         public int Start {
@@ -1141,7 +1186,7 @@ namespace Google.Protobuf.DescriptorProtos {
       }
 
       [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-      public sealed partial class ReservedRange : pb::IMessage<ReservedRange>, global::System.IEquatable<ReservedRange> {
+      public sealed partial class ReservedRange : pb::IMessage<ReservedRange>, global::System.IEquatable<ReservedRange>, pb::IDeepCloneable<ReservedRange> {
         private static readonly pb::MessageParser<ReservedRange> _parser = new pb::MessageParser<ReservedRange>(() => new ReservedRange());
         public static pb::MessageParser<ReservedRange> Parser { get { return _parser; } }
 
@@ -1156,9 +1201,16 @@ namespace Google.Protobuf.DescriptorProtos {
         }
 
         public ReservedRange() { }
+
         public ReservedRange(ReservedRange other) {
-          MergeFrom(other);
+          start_ = other.start_;
+          end_ = other.end_;
         }
+
+        public ReservedRange Clone() {
+          return new ReservedRange(this);
+        }
+
         public const int StartFieldNumber = 1;
         private int start_;
         public int Start {
@@ -1262,7 +1314,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class FieldDescriptorProto : pb::IMessage<FieldDescriptorProto>, global::System.IEquatable<FieldDescriptorProto> {
+  public sealed partial class FieldDescriptorProto : pb::IMessage<FieldDescriptorProto>, global::System.IEquatable<FieldDescriptorProto>, pb::IDeepCloneable<FieldDescriptorProto> {
     private static readonly pb::MessageParser<FieldDescriptorProto> _parser = new pb::MessageParser<FieldDescriptorProto>(() => new FieldDescriptorProto());
     public static pb::MessageParser<FieldDescriptorProto> Parser { get { return _parser; } }
 
@@ -1277,9 +1329,23 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public FieldDescriptorProto() { }
+
     public FieldDescriptorProto(FieldDescriptorProto other) {
-      MergeFrom(other);
+      name_ = other.name_;
+      number_ = other.number_;
+      label_ = other.label_;
+      type_ = other.type_;
+      typeName_ = other.typeName_;
+      extendee_ = other.extendee_;
+      defaultValue_ = other.defaultValue_;
+      oneofIndex_ = other.oneofIndex_;
+      Options = other.options_ != null ? other.Options.Clone() : null;
     }
+
+    public FieldDescriptorProto Clone() {
+      return new FieldDescriptorProto(this);
+    }
+
     public const int NameFieldNumber = 1;
     private string name_ = "";
     public string Name {
@@ -1583,7 +1649,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class OneofDescriptorProto : pb::IMessage<OneofDescriptorProto>, global::System.IEquatable<OneofDescriptorProto> {
+  public sealed partial class OneofDescriptorProto : pb::IMessage<OneofDescriptorProto>, global::System.IEquatable<OneofDescriptorProto>, pb::IDeepCloneable<OneofDescriptorProto> {
     private static readonly pb::MessageParser<OneofDescriptorProto> _parser = new pb::MessageParser<OneofDescriptorProto>(() => new OneofDescriptorProto());
     public static pb::MessageParser<OneofDescriptorProto> Parser { get { return _parser; } }
 
@@ -1598,9 +1664,15 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public OneofDescriptorProto() { }
+
     public OneofDescriptorProto(OneofDescriptorProto other) {
-      MergeFrom(other);
+      name_ = other.name_;
     }
+
+    public OneofDescriptorProto Clone() {
+      return new OneofDescriptorProto(this);
+    }
+
     public const int NameFieldNumber = 1;
     private string name_ = "";
     public string Name {
@@ -1675,7 +1747,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class EnumDescriptorProto : pb::IMessage<EnumDescriptorProto>, global::System.IEquatable<EnumDescriptorProto> {
+  public sealed partial class EnumDescriptorProto : pb::IMessage<EnumDescriptorProto>, global::System.IEquatable<EnumDescriptorProto>, pb::IDeepCloneable<EnumDescriptorProto> {
     private static readonly pb::MessageParser<EnumDescriptorProto> _parser = new pb::MessageParser<EnumDescriptorProto>(() => new EnumDescriptorProto());
     public static pb::MessageParser<EnumDescriptorProto> Parser { get { return _parser; } }
 
@@ -1690,9 +1762,17 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public EnumDescriptorProto() { }
+
     public EnumDescriptorProto(EnumDescriptorProto other) {
-      MergeFrom(other);
+      name_ = other.name_;
+      value_ = other.value_.Clone();
+      Options = other.options_ != null ? other.Options.Clone() : null;
+    }
+
+    public EnumDescriptorProto Clone() {
+      return new EnumDescriptorProto(this);
     }
+
     public const int NameFieldNumber = 1;
     private string name_ = "";
     public string Name {
@@ -1817,7 +1897,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class EnumValueDescriptorProto : pb::IMessage<EnumValueDescriptorProto>, global::System.IEquatable<EnumValueDescriptorProto> {
+  public sealed partial class EnumValueDescriptorProto : pb::IMessage<EnumValueDescriptorProto>, global::System.IEquatable<EnumValueDescriptorProto>, pb::IDeepCloneable<EnumValueDescriptorProto> {
     private static readonly pb::MessageParser<EnumValueDescriptorProto> _parser = new pb::MessageParser<EnumValueDescriptorProto>(() => new EnumValueDescriptorProto());
     public static pb::MessageParser<EnumValueDescriptorProto> Parser { get { return _parser; } }
 
@@ -1832,9 +1912,17 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public EnumValueDescriptorProto() { }
+
     public EnumValueDescriptorProto(EnumValueDescriptorProto other) {
-      MergeFrom(other);
+      name_ = other.name_;
+      number_ = other.number_;
+      Options = other.options_ != null ? other.Options.Clone() : null;
     }
+
+    public EnumValueDescriptorProto Clone() {
+      return new EnumValueDescriptorProto(this);
+    }
+
     public const int NameFieldNumber = 1;
     private string name_ = "";
     public string Name {
@@ -1961,7 +2049,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class ServiceDescriptorProto : pb::IMessage<ServiceDescriptorProto>, global::System.IEquatable<ServiceDescriptorProto> {
+  public sealed partial class ServiceDescriptorProto : pb::IMessage<ServiceDescriptorProto>, global::System.IEquatable<ServiceDescriptorProto>, pb::IDeepCloneable<ServiceDescriptorProto> {
     private static readonly pb::MessageParser<ServiceDescriptorProto> _parser = new pb::MessageParser<ServiceDescriptorProto>(() => new ServiceDescriptorProto());
     public static pb::MessageParser<ServiceDescriptorProto> Parser { get { return _parser; } }
 
@@ -1976,9 +2064,17 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public ServiceDescriptorProto() { }
+
     public ServiceDescriptorProto(ServiceDescriptorProto other) {
-      MergeFrom(other);
+      name_ = other.name_;
+      method_ = other.method_.Clone();
+      Options = other.options_ != null ? other.Options.Clone() : null;
+    }
+
+    public ServiceDescriptorProto Clone() {
+      return new ServiceDescriptorProto(this);
     }
+
     public const int NameFieldNumber = 1;
     private string name_ = "";
     public string Name {
@@ -2103,7 +2199,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class MethodDescriptorProto : pb::IMessage<MethodDescriptorProto>, global::System.IEquatable<MethodDescriptorProto> {
+  public sealed partial class MethodDescriptorProto : pb::IMessage<MethodDescriptorProto>, global::System.IEquatable<MethodDescriptorProto>, pb::IDeepCloneable<MethodDescriptorProto> {
     private static readonly pb::MessageParser<MethodDescriptorProto> _parser = new pb::MessageParser<MethodDescriptorProto>(() => new MethodDescriptorProto());
     public static pb::MessageParser<MethodDescriptorProto> Parser { get { return _parser; } }
 
@@ -2118,9 +2214,20 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public MethodDescriptorProto() { }
+
     public MethodDescriptorProto(MethodDescriptorProto other) {
-      MergeFrom(other);
+      name_ = other.name_;
+      inputType_ = other.inputType_;
+      outputType_ = other.outputType_;
+      Options = other.options_ != null ? other.Options.Clone() : null;
+      clientStreaming_ = other.clientStreaming_;
+      serverStreaming_ = other.serverStreaming_;
+    }
+
+    public MethodDescriptorProto Clone() {
+      return new MethodDescriptorProto(this);
     }
+
     public const int NameFieldNumber = 1;
     private string name_ = "";
     public string Name {
@@ -2319,7 +2426,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class FileOptions : pb::IMessage<FileOptions>, global::System.IEquatable<FileOptions> {
+  public sealed partial class FileOptions : pb::IMessage<FileOptions>, global::System.IEquatable<FileOptions>, pb::IDeepCloneable<FileOptions> {
     private static readonly pb::MessageParser<FileOptions> _parser = new pb::MessageParser<FileOptions>(() => new FileOptions());
     public static pb::MessageParser<FileOptions> Parser { get { return _parser; } }
 
@@ -2334,9 +2441,29 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public FileOptions() { }
+
     public FileOptions(FileOptions other) {
-      MergeFrom(other);
+      javaPackage_ = other.javaPackage_;
+      javaOuterClassname_ = other.javaOuterClassname_;
+      javaMultipleFiles_ = other.javaMultipleFiles_;
+      javaGenerateEqualsAndHash_ = other.javaGenerateEqualsAndHash_;
+      javaStringCheckUtf8_ = other.javaStringCheckUtf8_;
+      optimizeFor_ = other.optimizeFor_;
+      goPackage_ = other.goPackage_;
+      ccGenericServices_ = other.ccGenericServices_;
+      javaGenericServices_ = other.javaGenericServices_;
+      pyGenericServices_ = other.pyGenericServices_;
+      deprecated_ = other.deprecated_;
+      ccEnableArenas_ = other.ccEnableArenas_;
+      objcClassPrefix_ = other.objcClassPrefix_;
+      csharpNamespace_ = other.csharpNamespace_;
+      uninterpretedOption_ = other.uninterpretedOption_.Clone();
+    }
+
+    public FileOptions Clone() {
+      return new FileOptions(this);
     }
+
     public const int JavaPackageFieldNumber = 1;
     private string javaPackage_ = "";
     public string JavaPackage {
@@ -2757,7 +2884,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class MessageOptions : pb::IMessage<MessageOptions>, global::System.IEquatable<MessageOptions> {
+  public sealed partial class MessageOptions : pb::IMessage<MessageOptions>, global::System.IEquatable<MessageOptions>, pb::IDeepCloneable<MessageOptions> {
     private static readonly pb::MessageParser<MessageOptions> _parser = new pb::MessageParser<MessageOptions>(() => new MessageOptions());
     public static pb::MessageParser<MessageOptions> Parser { get { return _parser; } }
 
@@ -2772,9 +2899,19 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public MessageOptions() { }
+
     public MessageOptions(MessageOptions other) {
-      MergeFrom(other);
+      messageSetWireFormat_ = other.messageSetWireFormat_;
+      noStandardDescriptorAccessor_ = other.noStandardDescriptorAccessor_;
+      deprecated_ = other.deprecated_;
+      mapEntry_ = other.mapEntry_;
+      uninterpretedOption_ = other.uninterpretedOption_.Clone();
+    }
+
+    public MessageOptions Clone() {
+      return new MessageOptions(this);
     }
+
     public const int MessageSetWireFormatFieldNumber = 1;
     private bool messageSetWireFormat_;
     public bool MessageSetWireFormat {
@@ -2943,7 +3080,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class FieldOptions : pb::IMessage<FieldOptions>, global::System.IEquatable<FieldOptions> {
+  public sealed partial class FieldOptions : pb::IMessage<FieldOptions>, global::System.IEquatable<FieldOptions>, pb::IDeepCloneable<FieldOptions> {
     private static readonly pb::MessageParser<FieldOptions> _parser = new pb::MessageParser<FieldOptions>(() => new FieldOptions());
     public static pb::MessageParser<FieldOptions> Parser { get { return _parser; } }
 
@@ -2958,9 +3095,21 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public FieldOptions() { }
+
     public FieldOptions(FieldOptions other) {
-      MergeFrom(other);
+      ctype_ = other.ctype_;
+      packed_ = other.packed_;
+      jstype_ = other.jstype_;
+      lazy_ = other.lazy_;
+      deprecated_ = other.deprecated_;
+      weak_ = other.weak_;
+      uninterpretedOption_ = other.uninterpretedOption_.Clone();
     }
+
+    public FieldOptions Clone() {
+      return new FieldOptions(this);
+    }
+
     public const int CtypeFieldNumber = 1;
     private global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType ctype_ = global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType.STRING;
     public global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType Ctype {
@@ -3195,7 +3344,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class EnumOptions : pb::IMessage<EnumOptions>, global::System.IEquatable<EnumOptions> {
+  public sealed partial class EnumOptions : pb::IMessage<EnumOptions>, global::System.IEquatable<EnumOptions>, pb::IDeepCloneable<EnumOptions> {
     private static readonly pb::MessageParser<EnumOptions> _parser = new pb::MessageParser<EnumOptions>(() => new EnumOptions());
     public static pb::MessageParser<EnumOptions> Parser { get { return _parser; } }
 
@@ -3210,9 +3359,17 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public EnumOptions() { }
+
     public EnumOptions(EnumOptions other) {
-      MergeFrom(other);
+      allowAlias_ = other.allowAlias_;
+      deprecated_ = other.deprecated_;
+      uninterpretedOption_ = other.uninterpretedOption_.Clone();
+    }
+
+    public EnumOptions Clone() {
+      return new EnumOptions(this);
     }
+
     public const int AllowAliasFieldNumber = 2;
     private bool allowAlias_;
     public bool AllowAlias {
@@ -3333,7 +3490,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class EnumValueOptions : pb::IMessage<EnumValueOptions>, global::System.IEquatable<EnumValueOptions> {
+  public sealed partial class EnumValueOptions : pb::IMessage<EnumValueOptions>, global::System.IEquatable<EnumValueOptions>, pb::IDeepCloneable<EnumValueOptions> {
     private static readonly pb::MessageParser<EnumValueOptions> _parser = new pb::MessageParser<EnumValueOptions>(() => new EnumValueOptions());
     public static pb::MessageParser<EnumValueOptions> Parser { get { return _parser; } }
 
@@ -3348,9 +3505,16 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public EnumValueOptions() { }
+
     public EnumValueOptions(EnumValueOptions other) {
-      MergeFrom(other);
+      deprecated_ = other.deprecated_;
+      uninterpretedOption_ = other.uninterpretedOption_.Clone();
     }
+
+    public EnumValueOptions Clone() {
+      return new EnumValueOptions(this);
+    }
+
     public const int DeprecatedFieldNumber = 1;
     private bool deprecated_;
     public bool Deprecated {
@@ -3447,7 +3611,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class ServiceOptions : pb::IMessage<ServiceOptions>, global::System.IEquatable<ServiceOptions> {
+  public sealed partial class ServiceOptions : pb::IMessage<ServiceOptions>, global::System.IEquatable<ServiceOptions>, pb::IDeepCloneable<ServiceOptions> {
     private static readonly pb::MessageParser<ServiceOptions> _parser = new pb::MessageParser<ServiceOptions>(() => new ServiceOptions());
     public static pb::MessageParser<ServiceOptions> Parser { get { return _parser; } }
 
@@ -3462,9 +3626,16 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public ServiceOptions() { }
+
     public ServiceOptions(ServiceOptions other) {
-      MergeFrom(other);
+      deprecated_ = other.deprecated_;
+      uninterpretedOption_ = other.uninterpretedOption_.Clone();
+    }
+
+    public ServiceOptions Clone() {
+      return new ServiceOptions(this);
     }
+
     public const int DeprecatedFieldNumber = 33;
     private bool deprecated_;
     public bool Deprecated {
@@ -3561,7 +3732,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class MethodOptions : pb::IMessage<MethodOptions>, global::System.IEquatable<MethodOptions> {
+  public sealed partial class MethodOptions : pb::IMessage<MethodOptions>, global::System.IEquatable<MethodOptions>, pb::IDeepCloneable<MethodOptions> {
     private static readonly pb::MessageParser<MethodOptions> _parser = new pb::MessageParser<MethodOptions>(() => new MethodOptions());
     public static pb::MessageParser<MethodOptions> Parser { get { return _parser; } }
 
@@ -3576,9 +3747,16 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public MethodOptions() { }
+
     public MethodOptions(MethodOptions other) {
-      MergeFrom(other);
+      deprecated_ = other.deprecated_;
+      uninterpretedOption_ = other.uninterpretedOption_.Clone();
+    }
+
+    public MethodOptions Clone() {
+      return new MethodOptions(this);
     }
+
     public const int DeprecatedFieldNumber = 33;
     private bool deprecated_;
     public bool Deprecated {
@@ -3675,7 +3853,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class UninterpretedOption : pb::IMessage<UninterpretedOption>, global::System.IEquatable<UninterpretedOption> {
+  public sealed partial class UninterpretedOption : pb::IMessage<UninterpretedOption>, global::System.IEquatable<UninterpretedOption>, pb::IDeepCloneable<UninterpretedOption> {
     private static readonly pb::MessageParser<UninterpretedOption> _parser = new pb::MessageParser<UninterpretedOption>(() => new UninterpretedOption());
     public static pb::MessageParser<UninterpretedOption> Parser { get { return _parser; } }
 
@@ -3690,9 +3868,21 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public UninterpretedOption() { }
+
     public UninterpretedOption(UninterpretedOption other) {
-      MergeFrom(other);
+      name_ = other.name_.Clone();
+      identifierValue_ = other.identifierValue_;
+      positiveIntValue_ = other.positiveIntValue_;
+      negativeIntValue_ = other.negativeIntValue_;
+      doubleValue_ = other.doubleValue_;
+      stringValue_ = other.stringValue_;
+      aggregateValue_ = other.aggregateValue_;
     }
+
+    public UninterpretedOption Clone() {
+      return new UninterpretedOption(this);
+    }
+
     public const int NameFieldNumber = 2;
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart> name_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart>();
     public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart> Name {
@@ -3910,7 +4100,7 @@ namespace Google.Protobuf.DescriptorProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Types {
       [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-      public sealed partial class NamePart : pb::IMessage<NamePart>, global::System.IEquatable<NamePart> {
+      public sealed partial class NamePart : pb::IMessage<NamePart>, global::System.IEquatable<NamePart>, pb::IDeepCloneable<NamePart> {
         private static readonly pb::MessageParser<NamePart> _parser = new pb::MessageParser<NamePart>(() => new NamePart());
         public static pb::MessageParser<NamePart> Parser { get { return _parser; } }
 
@@ -3925,9 +4115,16 @@ namespace Google.Protobuf.DescriptorProtos {
         }
 
         public NamePart() { }
+
         public NamePart(NamePart other) {
-          MergeFrom(other);
+          namePart_ = other.namePart_;
+          isExtension_ = other.isExtension_;
         }
+
+        public NamePart Clone() {
+          return new NamePart(this);
+        }
+
         public const int NamePart_FieldNumber = 1;
         private string namePart_ = "";
         public string NamePart_ {
@@ -4031,7 +4228,7 @@ namespace Google.Protobuf.DescriptorProtos {
   }
 
   [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-  public sealed partial class SourceCodeInfo : pb::IMessage<SourceCodeInfo>, global::System.IEquatable<SourceCodeInfo> {
+  public sealed partial class SourceCodeInfo : pb::IMessage<SourceCodeInfo>, global::System.IEquatable<SourceCodeInfo>, pb::IDeepCloneable<SourceCodeInfo> {
     private static readonly pb::MessageParser<SourceCodeInfo> _parser = new pb::MessageParser<SourceCodeInfo>(() => new SourceCodeInfo());
     public static pb::MessageParser<SourceCodeInfo> Parser { get { return _parser; } }
 
@@ -4046,9 +4243,15 @@ namespace Google.Protobuf.DescriptorProtos {
     }
 
     public SourceCodeInfo() { }
+
     public SourceCodeInfo(SourceCodeInfo other) {
-      MergeFrom(other);
+      location_ = other.location_.Clone();
+    }
+
+    public SourceCodeInfo Clone() {
+      return new SourceCodeInfo(this);
     }
+
     public const int LocationFieldNumber = 1;
     private readonly pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location> location_ = new pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location>();
     public pbc::RepeatedField<global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location> Location {
@@ -4122,7 +4325,7 @@ namespace Google.Protobuf.DescriptorProtos {
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     public static partial class Types {
       [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
-      public sealed partial class Location : pb::IMessage<Location>, global::System.IEquatable<Location> {
+      public sealed partial class Location : pb::IMessage<Location>, global::System.IEquatable<Location>, pb::IDeepCloneable<Location> {
         private static readonly pb::MessageParser<Location> _parser = new pb::MessageParser<Location>(() => new Location());
         public static pb::MessageParser<Location> Parser { get { return _parser; } }
 
@@ -4137,9 +4340,19 @@ namespace Google.Protobuf.DescriptorProtos {
         }
 
         public Location() { }
+
         public Location(Location other) {
-          MergeFrom(other);
+          path_ = other.path_.Clone();
+          span_ = other.span_.Clone();
+          leadingComments_ = other.leadingComments_;
+          trailingComments_ = other.trailingComments_;
+          leadingDetachedComments_ = other.leadingDetachedComments_.Clone();
         }
+
+        public Location Clone() {
+          return new Location(this);
+        }
+
         public const int PathFieldNumber = 1;
         private readonly pbc::RepeatedField<int> path_ = new pbc::RepeatedField<int>();
         public pbc::RepeatedField<int> Path {

+ 18 - 0
csharp/src/ProtocolBuffers/IMessage.cs

@@ -93,4 +93,22 @@ namespace Google.Protobuf
         /// <param name="message">The message to merge with this one. Must not be null.</param>
         void MergeFrom(T message);
     }
+
+    /// <summary>
+    /// Generic interface for a deeply cloneable type.
+    /// <summary>
+    /// <remarks>
+    /// In practice, all generated messages implement this interface.
+    /// However, due to the type constraint on <c>T</c> in <see cref="IMessage{T}"/>,
+    /// it is simpler to keep this as a separate interface.
+    /// </remarks>
+    /// <typeparam name="T">The type itself, returned by the <see cref="Clone"/> method.</typeparam>
+    public interface IDeepCloneable<T>
+    {
+        /// <summary>
+        /// Creates a deep clone of this object.
+        /// </summary>
+        /// <returns>A deep clone of this object.</returns>
+        T Clone();
+    }
 }

+ 1 - 0
src/google/protobuf/compiler/csharp/csharp_field_base.h

@@ -47,6 +47,7 @@ class FieldGeneratorBase : public SourceGeneratorBase {
   FieldGeneratorBase(const FieldDescriptor* descriptor, int fieldOrdinal);
   ~FieldGeneratorBase();
 
+  virtual void GenerateCloningCode(io::Printer* printer) = 0;
   virtual void GenerateMembers(io::Printer* printer) = 0;
   virtual void GenerateMergingCode(io::Printer* printer) = 0;
   virtual void GenerateParsingCode(io::Printer* printer) = 0;

+ 51 - 8
src/google/protobuf/compiler/csharp/csharp_message.cc

@@ -179,7 +179,7 @@ void MessageGenerator::Generate(io::Printer* printer) {
   WriteGeneratedCodeAttributes(printer);
   printer->Print(
     vars,
-    "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$>, global::System.IEquatable<$class_name$> {\n");
+    "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$>, global::System.IEquatable<$class_name$>, pb::IDeepCloneable<$class_name$> {\n");
   printer->Indent();
 
   // All static fields and properties
@@ -213,16 +213,12 @@ void MessageGenerator::Generate(io::Printer* printer) {
     "}\n"
     "\n");
 
-  // Constructors
+  // Parameterless constructor
   printer->Print(
     vars,
-    "public $class_name$() { }\n");  // Public parameterless ctor.
+    "public $class_name$() { }\n\n");
 
-  printer->Print(
-    vars,
-    "public $class_name$($class_name$ other) {\n"
-    "  MergeFrom(other);\n"
-    "}\n");  // Merge ctor.
+  GenerateCloningCode(printer);
 
   // Fields/properties
   for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -303,6 +299,53 @@ void MessageGenerator::Generate(io::Printer* printer) {
 
 }
 
+void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
+  map<string, string> vars;
+  vars["class_name"] = class_name();
+    printer->Print(
+    vars,
+    "public $class_name$($class_name$ other) {\n");
+  printer->Indent();
+  // Clone non-oneof fields first
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    if (!descriptor_->field(i)->containing_oneof()) {
+      scoped_ptr<FieldGeneratorBase> generator(
+        CreateFieldGeneratorInternal(descriptor_->field(i)));
+      generator->GenerateCloningCode(printer);
+    }
+  }
+  // Clone just the right field for each oneof
+  for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) {
+    vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false);
+    vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true);
+    printer->Print(vars, "switch (other.$property_name$Case) {\n");
+    printer->Indent();
+    for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) {
+      const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j);
+      scoped_ptr<FieldGeneratorBase> generator(CreateFieldGeneratorInternal(field));
+      vars["field_property_name"] = GetPropertyName(field);
+      printer->Print(
+          vars,
+          "case $property_name$OneofCase.$field_property_name$:\n");
+      printer->Indent();
+      generator->GenerateCloningCode(printer);
+      printer->Print("break;\n");
+      printer->Outdent();
+    }
+    printer->Outdent();
+    printer->Print("}\n\n");
+  }
+
+  printer->Outdent();
+  printer->Print("}\n\n");
+
+  printer->Print(
+    vars,
+    "public $class_name$ Clone() {\n"
+    "  return new $class_name$(this);\n"
+    "}\n\n");
+}
+
 void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
     map<string, string> vars;
     vars["class_name"] = class_name();

+ 1 - 0
src/google/protobuf/compiler/csharp/csharp_message.h

@@ -50,6 +50,7 @@ class MessageGenerator : public SourceGeneratorBase {
   MessageGenerator(const Descriptor* descriptor);
   ~MessageGenerator();
 
+  void GenerateCloningCode(io::Printer* printer);
   void GenerateFrameworkMethods(io::Printer* printer);
   void GenerateStaticVariables(io::Printer* printer);
   void GenerateStaticVariableInitializers(io::Printer* printer);

+ 10 - 0
src/google/protobuf/compiler/csharp/csharp_message_field.cc

@@ -125,6 +125,11 @@ void MessageFieldGenerator::WriteToString(io::Printer* printer) {
     "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n");
 }
 
+void MessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$property_name$ = other.$has_property_check$ ? other.$property_name$.Clone() : null;\n");
+}
+
 MessageOneofFieldGenerator::MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
 						       int fieldOrdinal)
     : MessageFieldGenerator(descriptor, fieldOrdinal) {
@@ -166,6 +171,11 @@ void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) {
     "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n");
 }
 
+void MessageOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$property_name$ = other.$property_name$.Clone();\n");
+}
+
 }  // namespace csharp
 }  // namespace compiler
 }  // namespace protobuf

+ 2 - 0
src/google/protobuf/compiler/csharp/csharp_message_field.h

@@ -46,6 +46,7 @@ class MessageFieldGenerator : public FieldGeneratorBase {
   MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
   ~MessageFieldGenerator();
 
+  virtual void GenerateCloningCode(io::Printer* printer);
   virtual void GenerateMembers(io::Printer* printer);
   virtual void GenerateMergingCode(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer);
@@ -65,6 +66,7 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator {
   MessageOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
   ~MessageOneofFieldGenerator();
 
+  virtual void GenerateCloningCode(io::Printer* printer);
   virtual void GenerateMembers(io::Printer* printer);
   virtual void WriteToString(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer);

+ 10 - 0
src/google/protobuf/compiler/csharp/csharp_primitive_field.cc

@@ -146,6 +146,11 @@ void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) {
     "PrintField(\"$descriptor_name$\", $has_property_check$, $property_name$, writer);\n");
 }
 
+void PrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$name$_ = other.$name$_;\n");
+}
+
 PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator(
     const FieldDescriptor* descriptor, int fieldOrdinal)
     : PrimitiveFieldGenerator(descriptor, fieldOrdinal) {
@@ -189,6 +194,11 @@ void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) {
       "$property_name$ = input.Read$capitalized_type_name$();\n");
 }
 
+void PrimitiveOneofFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$property_name$ = other.$property_name$;\n");
+}
+
 }  // namespace csharp
 }  // namespace compiler
 }  // namespace protobuf

+ 2 - 0
src/google/protobuf/compiler/csharp/csharp_primitive_field.h

@@ -46,6 +46,7 @@ class PrimitiveFieldGenerator : public FieldGeneratorBase {
   PrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
   ~PrimitiveFieldGenerator();
 
+  virtual void GenerateCloningCode(io::Printer* printer);
   virtual void GenerateMembers(io::Printer* printer);
   virtual void GenerateMergingCode(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer);
@@ -68,6 +69,7 @@ class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
   PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
   ~PrimitiveOneofFieldGenerator();
 
+  virtual void GenerateCloningCode(io::Printer* printer);
   virtual void GenerateMembers(io::Printer* printer);
   virtual void WriteToString(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer);

+ 5 - 0
src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc

@@ -142,6 +142,11 @@ void RepeatedEnumFieldGenerator::WriteToString(io::Printer* printer) {
     "PrintField(\"$descriptor_name$\", $name$_, writer);\n");
 }
 
+void RepeatedEnumFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$name$_ = other.$name$_.Clone();\n");
+}
+
 }  // namespace csharp
 }  // namespace compiler
 }  // namespace protobuf

+ 1 - 0
src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h

@@ -48,6 +48,7 @@ class RepeatedEnumFieldGenerator : public FieldGeneratorBase {
   RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
   ~RepeatedEnumFieldGenerator();
 
+  virtual void GenerateCloningCode(io::Printer* printer);
   virtual void GenerateMembers(io::Printer* printer);
   virtual void GenerateMergingCode(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer);

+ 5 - 0
src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc

@@ -118,6 +118,11 @@ void RepeatedMessageFieldGenerator::WriteToString(io::Printer* printer) {
     "PrintField(\"$field_name$\", $name$_, writer);\n");
 }
 
+void RepeatedMessageFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$name$_ = other.$name$_.Clone();\n");
+}
+
 }  // namespace csharp
 }  // namespace compiler
 }  // namespace protobuf

+ 1 - 0
src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h

@@ -46,6 +46,7 @@ class RepeatedMessageFieldGenerator : public FieldGeneratorBase {
   RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
   ~RepeatedMessageFieldGenerator();
 
+  virtual void GenerateCloningCode(io::Printer* printer);
   virtual void GenerateMembers(io::Printer* printer);
   virtual void GenerateMergingCode(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer);

+ 5 - 0
src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc

@@ -148,6 +148,11 @@ void RepeatedPrimitiveFieldGenerator::WriteToString(io::Printer* printer) {
     "PrintField(\"$descriptor_name$\", $name$_, writer);\n");
 }
 
+void RepeatedPrimitiveFieldGenerator::GenerateCloningCode(io::Printer* printer) {
+  printer->Print(variables_,
+    "$name$_ = other.$name$_.Clone();\n");
+}
+
 }  // namespace csharp
 }  // namespace compiler
 }  // namespace protobuf

+ 1 - 0
src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h

@@ -46,6 +46,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase {
   RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal);
   ~RepeatedPrimitiveFieldGenerator();
 
+  virtual void GenerateCloningCode(io::Printer* printer);
   virtual void GenerateMembers(io::Printer* printer);
   virtual void GenerateMergingCode(io::Printer* printer);
   virtual void GenerateParsingCode(io::Printer* printer);

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini