diff --git a/csharp/src/Google.Protobuf/ByteString.cs b/csharp/src/Google.Protobuf/ByteString.cs index e361dd11fe..fc5d925fa7 100644 --- a/csharp/src/Google.Protobuf/ByteString.cs +++ b/csharp/src/Google.Protobuf/ByteString.cs @@ -10,6 +10,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Security; @@ -23,6 +24,8 @@ namespace Google.Protobuf /// Immutable array of bytes. /// [SecuritySafeCritical] + [DebuggerDisplay("Length = {Length}")] + [DebuggerTypeProxy(typeof(ByteStringDebugView))] public sealed class ByteString : IEnumerable, IEquatable { private static readonly ByteString empty = new ByteString(new byte[0]); @@ -400,5 +403,18 @@ namespace Google.Protobuf outputStream.Write(array, 0, array.Length); } } + + private sealed class ByteStringDebugView + { + private readonly ByteString data; + + public ByteStringDebugView(ByteString data) + { + this.data = data; + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public byte[] Items => data.bytes.ToArray(); + } } } \ No newline at end of file diff --git a/csharp/src/Google.Protobuf/Collections/MapField.cs b/csharp/src/Google.Protobuf/Collections/MapField.cs index 2e18976578..f0be958303 100644 --- a/csharp/src/Google.Protobuf/Collections/MapField.cs +++ b/csharp/src/Google.Protobuf/Collections/MapField.cs @@ -11,6 +11,7 @@ using Google.Protobuf.Compatibility; using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Security; @@ -43,6 +44,8 @@ namespace Google.Protobuf.Collections /// in future versions. /// /// + [DebuggerDisplay("Count = {Count}")] + [DebuggerTypeProxy(typeof(MapField<,>.MapFieldDebugView))] public sealed class MapField : IDeepCloneable>, IDictionary, IEquatable>, IDictionary, IReadOnlyDictionary { private static readonly EqualityComparer ValueEqualityComparer = ProtobufEqualityComparers.GetEqualityComparer(); @@ -683,5 +686,18 @@ namespace Google.Protobuf.Collections } } } + + private sealed class MapFieldDebugView + { + private readonly MapField map; + + public MapFieldDebugView(MapField map) + { + this.map = map; + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public KeyValuePair[] Items => map.list.ToArray(); + } } } diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs index 38e70156c9..8bf410aa85 100644 --- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs +++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs @@ -10,7 +10,9 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.IO; +using System.Linq; using System.Security; namespace Google.Protobuf.Collections @@ -24,6 +26,8 @@ namespace Google.Protobuf.Collections /// supported by Protocol Buffers but nor does it guarantee that all operations will work in such cases. /// /// The element type of the repeated field. + [DebuggerDisplay("Count = {Count}")] + [DebuggerTypeProxy(typeof(RepeatedField<>.RepeatedFieldDebugView))] public sealed class RepeatedField : IList, IList, IDeepCloneable>, IEquatable>, IReadOnlyList { private static readonly EqualityComparer EqualityComparer = ProtobufEqualityComparers.GetEqualityComparer(); @@ -642,5 +646,18 @@ namespace Google.Protobuf.Collections } } #endregion + + private sealed class RepeatedFieldDebugView + { + private readonly RepeatedField list; + + public RepeatedFieldDebugView(RepeatedField list) + { + this.list = list; + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public T[] Items => list.ToArray(); + } } } diff --git a/csharp/src/Google.Protobuf/Reflection/CustomOptions.cs b/csharp/src/Google.Protobuf/Reflection/CustomOptions.cs index 21ec57a386..43b5a4c5ab 100644 --- a/csharp/src/Google.Protobuf/Reflection/CustomOptions.cs +++ b/csharp/src/Google.Protobuf/Reflection/CustomOptions.cs @@ -8,8 +8,10 @@ #endregion using Google.Protobuf.Collections; +using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; @@ -38,6 +40,8 @@ namespace Google.Protobuf.Reflection /// all the set values are merged together. /// /// + [DebuggerDisplay("Count = {DebugCount}")] + [DebuggerTypeProxy(typeof(CustomOptionsDebugView))] public sealed class CustomOptions { private const string UnreferencedCodeMessage = "CustomOptions is incompatible with trimming."; @@ -290,5 +294,20 @@ namespace Google.Protobuf.Reflection value = default; return false; } + + private int DebugCount => values?.Count ?? 0; + + private sealed class CustomOptionsDebugView + { + private readonly CustomOptions customOptions; + + public CustomOptionsDebugView(CustomOptions customOptions) + { + this.customOptions = customOptions; + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public KeyValuePair[] Items => customOptions.values?.ToArray() ?? new KeyValuePair[0]; + } } } diff --git a/csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs b/csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs index 34a73d6abe..e70b23ad1f 100644 --- a/csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs +++ b/csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs @@ -8,12 +8,14 @@ #endregion using System.Collections.Generic; +using System.Diagnostics; namespace Google.Protobuf.Reflection { /// /// Base class for nearly all descriptors, providing common functionality. /// + [DebuggerDisplay("Type = {GetType().Name,nq}, FullName = {FullName}")] public abstract class DescriptorBase : IDescriptor { internal DescriptorBase(FileDescriptor file, string fullName, int index) diff --git a/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs b/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs index 9fcad8942f..5ce2cfe50f 100644 --- a/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs +++ b/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics; using System.Linq; namespace Google.Protobuf.Reflection @@ -16,6 +17,8 @@ namespace Google.Protobuf.Reflection /// /// A collection to simplify retrieving the descriptors of extensions in a descriptor for a message /// + [DebuggerDisplay("Count = {UnorderedExtensions.Count}")] + [DebuggerTypeProxy(typeof(ExtensionCollectionDebugView))] public sealed class ExtensionCollection { private IDictionary> extensionsByTypeInDeclarationOrder; @@ -98,5 +101,18 @@ namespace Google.Protobuf.Reflection extensionsByTypeInNumberOrder = declarationOrder .ToDictionary(kvp => kvp.Key, kvp => (IList)new ReadOnlyCollection(kvp.Value.OrderBy(field => field.FieldNumber).ToArray())); } + + private sealed class ExtensionCollectionDebugView + { + private readonly ExtensionCollection list; + + public ExtensionCollectionDebugView(ExtensionCollection list) + { + this.list = list; + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public FieldDescriptor[] Items => list.UnorderedExtensions.ToArray(); + } } } diff --git a/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs b/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs index f5ef62c9b8..a4748c53db 100644 --- a/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs +++ b/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs @@ -8,6 +8,7 @@ #endregion using System; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; namespace Google.Protobuf.Reflection @@ -17,6 +18,7 @@ namespace Google.Protobuf.Reflection /// These are constructed as required, and are not long-lived. Hand-written code should /// never need to use this type. /// + [DebuggerDisplay("ClrType = {ClrType}")] public sealed class GeneratedClrTypeInfo { private static readonly string[] EmptyNames = new string[0]; diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs index dfa63e47cf..37ca0f152e 100644 --- a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs +++ b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs @@ -10,6 +10,7 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; @@ -326,6 +327,8 @@ namespace Google.Protobuf.Reflection /// /// A collection to simplify retrieving the field accessor for a particular field. /// + [DebuggerDisplay("Count = {InFieldNumberOrder().Count}")] + [DebuggerTypeProxy(typeof(FieldCollectionDebugView))] public sealed class FieldCollection { private readonly MessageDescriptor messageDescriptor; @@ -398,6 +401,19 @@ namespace Google.Protobuf.Reflection return fieldDescriptor; } } + + private sealed class FieldCollectionDebugView + { + private readonly FieldCollection collection; + + public FieldCollectionDebugView(FieldCollection collection) + { + this.collection = collection; + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public FieldDescriptor[] Items => collection.InFieldNumberOrder().ToArray(); + } } } } diff --git a/csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs b/csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs index b1bf30b714..f0ab81cbe7 100644 --- a/csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs +++ b/csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs @@ -8,6 +8,7 @@ #endregion using System.Collections.Generic; +using System.Diagnostics; using System.Linq; namespace Google.Protobuf.Reflection @@ -15,6 +16,8 @@ namespace Google.Protobuf.Reflection /// /// An immutable registry of types which can be looked up by their full name. /// + [DebuggerDisplay("Count = {fullNameToMessageMap.Count}")] + [DebuggerTypeProxy(typeof(TypeRegistryDebugView))] public sealed class TypeRegistry { /// @@ -156,5 +159,18 @@ namespace Google.Protobuf.Reflection return new TypeRegistry(types); } } + + private sealed class TypeRegistryDebugView + { + private readonly TypeRegistry list; + + public TypeRegistryDebugView(TypeRegistry list) + { + this.list = list; + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public KeyValuePair[] Items => list.fullNameToMessageMap.ToArray(); + } } } diff --git a/csharp/src/Google.Protobuf/UnknownFieldSet.cs b/csharp/src/Google.Protobuf/UnknownFieldSet.cs index 4fab6156dc..d0963d257d 100644 --- a/csharp/src/Google.Protobuf/UnknownFieldSet.cs +++ b/csharp/src/Google.Protobuf/UnknownFieldSet.cs @@ -9,6 +9,8 @@ using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; using System.Security; namespace Google.Protobuf @@ -22,6 +24,8 @@ namespace Google.Protobuf /// /// Most users will never need to use this class directly. /// + [DebuggerDisplay("Count = {fields.Count}")] + [DebuggerTypeProxy(typeof(UnknownFieldSetDebugView))] public sealed partial class UnknownFieldSet { private readonly IDictionary fields = new Dictionary(); @@ -93,7 +97,7 @@ namespace Google.Protobuf } UnknownFieldSet otherSet = other as UnknownFieldSet; IDictionary otherFields = otherSet.fields; - if (fields.Count != otherFields.Count) + if (fields.Count != otherFields.Count) { return false; } @@ -360,6 +364,19 @@ namespace Google.Protobuf unknownFields.MergeFrom(other); return unknownFields; } + + private sealed class UnknownFieldSetDebugView + { + private readonly UnknownFieldSet set; + + public UnknownFieldSetDebugView(UnknownFieldSet set) + { + this.set = set; + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public KeyValuePair[] Items => set.fields.ToArray(); + } } }