Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify debug views of immutable dictionaries #100745

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 57 additions & 5 deletions src/libraries/Common/tests/System/Collections/DebugView.Tests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Concurrent;
using System.Collections.Frozen;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
Expand Down Expand Up @@ -47,8 +50,8 @@ private static IEnumerable<object[]> TestDebuggerAttributes_GenericDictionaries(
new ("[\"Two\"]", "2"),
}
};
CustomKeyedCollection<string, int> collection = new ();
collection.GetKeyForItemHandler = value => (2 * value).ToString();
CustomKeyedCollection<string, int> collection = new();
collection.GetKeyForItemHandler = value => (2 * value).ToString();
collection.InsertItem(0, 1);
collection.InsertItem(1, 3);
yield return new object[] { collection,
Expand All @@ -58,6 +61,53 @@ private static IEnumerable<object[]> TestDebuggerAttributes_GenericDictionaries(
new ("[\"6\"]", "3"),
}
};

yield return new object[] { new ConcurrentDictionary<int, string>(new KeyValuePair<int, string>[] { new(1, "One"), new(2, "Two") }),
new KeyValuePair<string, string>[]
{
new ("[1]", "\"One\""),
new ("[2]", "\"Two\""),
}
};
}

private static IEnumerable<object[]> TestDebuggerAttributes_AdditionalGenericDictionaries()
{
yield return new object[] { new Dictionary<int, string> { { 1, "One" }, { 2, "Two" } }.ToFrozenDictionary(),
new KeyValuePair<string, string>[]
{
new ("[1]", "\"One\""),
new ("[2]", "\"Two\""),
}
};
yield return new object[] { new Dictionary<int, string> { { 1, "One" }, { 2, "Two" } }.ToImmutableDictionary(),
new KeyValuePair<string, string>[]
{
new ("[1]", "\"One\""),
new ("[2]", "\"Two\""),
}
};
yield return new object[] { new Dictionary<int, string> { { 1, "One" }, { 2, "Two" } }.ToImmutableDictionary().ToBuilder(),
new KeyValuePair<string, string>[]
{
new ("[1]", "\"One\""),
new ("[2]", "\"Two\""),
}
};
yield return new object[] { new Dictionary<int, string> { { 1, "One" }, { 2, "Two" } }.ToImmutableSortedDictionary(),
new KeyValuePair<string, string>[]
{
new ("[1]", "\"One\""),
new ("[2]", "\"Two\""),
}
};
yield return new object[] { new Dictionary<int, string> { { 1, "One" }, { 2, "Two" } }.ToImmutableSortedDictionary().ToBuilder(),
new KeyValuePair<string, string>[]
{
new ("[1]", "\"One\""),
new ("[2]", "\"Two\""),
}
};
}

private static IEnumerable<object[]> TestDebuggerAttributes_NonGenericDictionaries()
Expand Down Expand Up @@ -162,12 +212,14 @@ private static IEnumerable<object[]> TestDebuggerAttributes_ListInputs()

public static IEnumerable<object[]> TestDebuggerAttributes_InputsPresentedAsDictionary()
{
var testCases = TestDebuggerAttributes_NonGenericDictionaries()
.Concat(TestDebuggerAttributes_AdditionalGenericDictionaries());
#if !NETFRAMEWORK
return TestDebuggerAttributes_NonGenericDictionaries()
return testCases
.Concat(TestDebuggerAttributes_GenericDictionaries());
#else
// In .Net Framework only non-generic dictionaries are displayed in a dictionary format by the debugger.
return TestDebuggerAttributes_NonGenericDictionaries();
// In .Net Framework, the generic dictionaries that are part of the framework are displayed in a list format by the debugger.
return testCases;
#endif
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
Link="System\Collections\HashHelpers.cs" />
<Compile Include="$(CoreLibSharedDir)System\Collections\Concurrent\IProducerConsumerCollectionDebugView.cs"
Link="System\Collections\Concurrent\IProducerConsumerCollectionDebugView.cs" />
<Compile Include="$(CoreLibSharedDir)System\Collections\Generic\DebugViewDictionaryItem.cs"
Link="Common\System\Collections\Generic\DebugViewDictionaryItem.cs" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2733,12 +2733,17 @@ public IDictionaryDebugView(IDictionary<TKey, TValue> dictionary)
}

[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePair<TKey, TValue>[] Items
public DebugViewDictionaryItem<TKey, TValue>[] Items
{
get
{
var items = new KeyValuePair<TKey, TValue>[_dictionary.Count];
_dictionary.CopyTo(items, 0);
var keyValuePairs = new KeyValuePair<TKey, TValue>[_dictionary.Count];
_dictionary.CopyTo(keyValuePairs, 0);
var items = new DebugViewDictionaryItem<TKey, TValue>[keyValuePairs.Length];
for (int i = 0; i < items.Length; i++)
{
items[i] = new DebugViewDictionaryItem<TKey, TValue>(keyValuePairs[i]);
}
return items;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -629,27 +629,6 @@ public static void TestConstructor_ConcurrencyLevel(int concurrencyLevel)
Assert.Equal(2, dictionary.Count);
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
public static void TestDebuggerAttributes()
{
DebuggerAttributes.ValidateDebuggerDisplayReferences(new ConcurrentDictionary<string, int>());
ConcurrentDictionary<string, int> dict = new ConcurrentDictionary<string, int>();
dict.TryAdd("One", 1);
dict.TryAdd("Two", 2);
DebuggerAttributeInfo info = DebuggerAttributes.ValidateDebuggerTypeProxyProperties(dict);
PropertyInfo itemProperty = info.Properties.Single(pr => pr.GetCustomAttribute<DebuggerBrowsableAttribute>().State == DebuggerBrowsableState.RootHidden);
KeyValuePair<string, int>[] items = itemProperty.GetValue(info.Instance) as KeyValuePair<string, int>[];
Assert.Equal(dict, items);
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
public static void TestDebuggerAttributes_Null()
{
Type proxyType = DebuggerAttributes.GetProxyType(new ConcurrentDictionary<string, int>());
TargetInvocationException tie = Assert.Throws<TargetInvocationException>(() => Activator.CreateInstance(proxyType, (object)null));
Assert.IsType<ArgumentNullException>(tie.InnerException);
}

[Fact]
public static void TestNullComparer()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,10 @@ The System.Collections.Immutable library is built-in as part of the shared frame
<Compile Include="System\Collections\Frozen\String\LengthBucketsFrozenSet.AlternateLookup.cs" />
<Compile Include="System\Collections\Frozen\String\OrdinalStringFrozenDictionary.AlternateLookup.cs" />
<Compile Include="System\Collections\Frozen\String\OrdinalStringFrozenSet.AlternateLookup.cs" />
<Compile Include="$(CoreLibSharedDir)System\Collections\Generic\DebugViewDictionaryItem.cs"
Link="Common\System\Collections\Generic\DebugViewDictionaryItem.cs" />
<Compile Include="$(CoreLibSharedDir)System\Collections\Generic\IDictionaryDebugView.cs"
Link="Common\System\Collections\Generic\IDictionaryDebugView.cs" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp'">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
/// </para>
/// </remarks>
[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(typeof(ImmutableDictionaryBuilderDebuggerProxy<,>))]
[DebuggerTypeProxy(typeof(IDictionaryDebugView<,>))]

Check failure on line 30 in src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.Builder.cs

View check run for this annotation

Azure Pipelines / runtime-dev-innerloop (Build linux-x64 debug Libraries_AllConfigurations)

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.Builder.cs#L30

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.Builder.cs(30,35): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'IDictionaryDebugView<,>' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.Builder.cs

View check run for this annotation

Azure Pipelines / runtime-dev-innerloop

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.Builder.cs#L30

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableDictionary_2.Builder.cs(30,35): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'IDictionaryDebugView<,>' could not be found (are you missing a using directive or an assembly reference?)
public sealed class Builder : IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>, IDictionary
{
/// <summary>
Expand Down Expand Up @@ -709,36 +709,4 @@
}
}
}

/// <summary>
/// A simple view of the immutable collection that the debugger can show to the developer.
/// </summary>
internal sealed class ImmutableDictionaryBuilderDebuggerProxy<TKey, TValue> where TKey : notnull
{
/// <summary>
/// The collection to be enumerated.
/// </summary>
private readonly ImmutableDictionary<TKey, TValue>.Builder _map;

/// <summary>
/// The simple view of the collection.
/// </summary>
private KeyValuePair<TKey, TValue>[]? _contents;

/// <summary>
/// Initializes a new instance of the <see cref="ImmutableDictionaryBuilderDebuggerProxy{TKey, TValue}"/> class.
/// </summary>
/// <param name="map">The collection to display in the debugger</param>
public ImmutableDictionaryBuilderDebuggerProxy(ImmutableDictionary<TKey, TValue>.Builder map)
{
Requires.NotNull(map, nameof(map));
_map = map;
}

/// <summary>
/// Gets a simple debugger-viewable collection.
/// </summary>
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePair<TKey, TValue>[] Contents => _contents ??= _map.ToArray(_map.Count);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,38 @@
/// </summary>
/// <typeparam name="TKey">The type of the dictionary's keys.</typeparam>
/// <typeparam name="TValue">The type of the dictionary's values.</typeparam>
internal sealed class ImmutableDictionaryDebuggerProxy<TKey, TValue> : ImmutableEnumerableDebuggerProxy<KeyValuePair<TKey, TValue>> where TKey : notnull
/// <remarks>
/// This class should only be used with immutable dictionaries, since it
/// caches the dictionary into an array for display in the debugger.
/// </remarks>
internal sealed class ImmutableDictionaryDebuggerProxy<TKey, TValue> where TKey : notnull
{
/// <summary>
/// The dictionary to show to the debugger.
/// </summary>
private readonly IReadOnlyDictionary<TKey, TValue> _dictionary;

/// <summary>
/// The contents of the dictionary, cached into an array.
/// </summary>
private DebugViewDictionaryItem<TKey, TValue>[]? _cachedContents;

Check failure on line 29 in src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableEnumerableDebuggerProxy.cs

View check run for this annotation

Azure Pipelines / runtime-dev-innerloop (Build linux-x64 debug Libraries_AllConfigurations)

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableEnumerableDebuggerProxy.cs#L29

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableEnumerableDebuggerProxy.cs(29,17): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'DebugViewDictionaryItem<,>' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 29 in src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableEnumerableDebuggerProxy.cs

View check run for this annotation

Azure Pipelines / runtime-dev-innerloop

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableEnumerableDebuggerProxy.cs#L29

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableEnumerableDebuggerProxy.cs(29,17): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'DebugViewDictionaryItem<,>' could not be found (are you missing a using directive or an assembly reference?)

/// <summary>
/// Initializes a new instance of the <see cref="ImmutableDictionaryDebuggerProxy{TKey, TValue}"/> class.
/// </summary>
/// <param name="dictionary">The enumerable to show in the debugger.</param>
/// <param name="dictionary">The dictionary to show in the debugger.</param>
public ImmutableDictionaryDebuggerProxy(IReadOnlyDictionary<TKey, TValue> dictionary)
: base(enumerable: dictionary)
{
Requires.NotNull(dictionary, nameof(dictionary));
_dictionary = dictionary;
}

/// <summary>
/// Gets the contents of the dictionary for display in the debugger.
/// </summary>
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public DebugViewDictionaryItem<TKey, TValue>[] Contents => _cachedContents

Check failure on line 45 in src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableEnumerableDebuggerProxy.cs

View check run for this annotation

Azure Pipelines / runtime-dev-innerloop (Build linux-x64 debug Libraries_AllConfigurations)

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableEnumerableDebuggerProxy.cs#L45

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableEnumerableDebuggerProxy.cs(45,16): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'DebugViewDictionaryItem<,>' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 45 in src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableEnumerableDebuggerProxy.cs

View check run for this annotation

Azure Pipelines / runtime-dev-innerloop

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableEnumerableDebuggerProxy.cs#L45

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableEnumerableDebuggerProxy.cs(45,16): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'DebugViewDictionaryItem<,>' could not be found (are you missing a using directive or an assembly reference?)
??= _dictionary.Select(kv => new DebugViewDictionaryItem<TKey, TValue>(kv)).ToArray(_dictionary.Count);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
/// </para>
/// </remarks>
[DebuggerDisplay("Count = {Count}")]
[DebuggerTypeProxy(typeof(ImmutableSortedDictionaryBuilderDebuggerProxy<,>))]
[DebuggerTypeProxy(typeof(IDictionaryDebugView<,>))]

Check failure on line 28 in src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedDictionary_2.Builder.cs

View check run for this annotation

Azure Pipelines / runtime-dev-innerloop (Build linux-x64 debug Libraries_AllConfigurations)

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedDictionary_2.Builder.cs#L28

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedDictionary_2.Builder.cs(28,35): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'IDictionaryDebugView<,>' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 28 in src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedDictionary_2.Builder.cs

View check run for this annotation

Azure Pipelines / runtime-dev-innerloop (Build linux-x64 debug Libraries_AllConfigurations)

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedDictionary_2.Builder.cs#L28

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedDictionary_2.Builder.cs(28,35): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'IDictionaryDebugView<,>' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 28 in src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedDictionary_2.Builder.cs

View check run for this annotation

Azure Pipelines / runtime-dev-innerloop

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedDictionary_2.Builder.cs#L28

src/libraries/System.Collections.Immutable/src/System/Collections/Immutable/ImmutableSortedDictionary_2.Builder.cs(28,35): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'IDictionaryDebugView<,>' could not be found (are you missing a using directive or an assembly reference?)
public sealed class Builder : IDictionary<TKey, TValue>, IReadOnlyDictionary<TKey, TValue>, IDictionary
{
/// <summary>
Expand Down Expand Up @@ -645,35 +645,4 @@
#endregion
}
}
/// <summary>
/// A simple view of the immutable collection that the debugger can show to the developer.
/// </summary>
internal sealed class ImmutableSortedDictionaryBuilderDebuggerProxy<TKey, TValue> where TKey : notnull
{
/// <summary>
/// The collection to be enumerated.
/// </summary>
private readonly ImmutableSortedDictionary<TKey, TValue>.Builder _map;

/// <summary>
/// The simple view of the collection.
/// </summary>
private KeyValuePair<TKey, TValue>[]? _contents;

/// <summary>
/// Initializes a new instance of the <see cref="ImmutableSortedDictionaryBuilderDebuggerProxy{TKey, TValue}"/> class.
/// </summary>
/// <param name="map">The collection to display in the debugger</param>
public ImmutableSortedDictionaryBuilderDebuggerProxy(ImmutableSortedDictionary<TKey, TValue>.Builder map)
{
Requires.NotNull(map, nameof(map));
_map = map;
}

/// <summary>
/// Gets a simple debugger-viewable collection.
/// </summary>
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
public KeyValuePair<TKey, TValue>[] Contents => _contents ??= _map.ToArray(_map.Count);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -255,27 +255,6 @@ public void GetValueOrDefaultOfConcreteType()
Assert.Equal(5, populated.GetValueOrDefault("a", 1));
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
public void DebuggerAttributesValid()
{
DebuggerAttributes.ValidateDebuggerDisplayReferences(ImmutableDictionary.CreateBuilder<string, int>());
ImmutableDictionary<int, string>.Builder builder = ImmutableDictionary.CreateBuilder<int, string>();
builder.Add(1, "One");
builder.Add(2, "Two");
DebuggerAttributeInfo info = DebuggerAttributes.ValidateDebuggerTypeProxyProperties(builder);
PropertyInfo itemProperty = info.Properties.Single(pr => pr.GetCustomAttribute<DebuggerBrowsableAttribute>().State == DebuggerBrowsableState.RootHidden);
KeyValuePair<int, string>[] items = itemProperty.GetValue(info.Instance) as KeyValuePair<int, string>[];
Assert.Equal(builder, items);
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
public static void TestDebuggerAttributes_Null()
{
Type proxyType = DebuggerAttributes.GetProxyType(ImmutableHashSet.Create<string>());
TargetInvocationException tie = Assert.Throws<TargetInvocationException>(() => Activator.CreateInstance(proxyType, (object)null));
Assert.IsType<ArgumentNullException>(tie.InnerException);
}

[Fact]
public void ToImmutableDictionary()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -349,28 +349,6 @@ public void EnumeratorRecyclingMisuse()
enumerator.Dispose();
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
public void DebuggerAttributesValid()
{
DebuggerAttributes.ValidateDebuggerDisplayReferences(ImmutableDictionary.Create<int, int>());
ImmutableDictionary<string, int> dict = ImmutableDictionary.Create<string, int>().Add("One", 1).Add("Two", 2);
DebuggerAttributeInfo info = DebuggerAttributes.ValidateDebuggerTypeProxyProperties(dict);

object rootNode = DebuggerAttributes.GetFieldValue(ImmutableDictionary.Create<string, string>(), "_root");
DebuggerAttributes.ValidateDebuggerDisplayReferences(rootNode);
PropertyInfo itemProperty = info.Properties.Single(pr => pr.GetCustomAttribute<DebuggerBrowsableAttribute>().State == DebuggerBrowsableState.RootHidden);
KeyValuePair<string, int>[] items = itemProperty.GetValue(info.Instance) as KeyValuePair<string, int>[];
Assert.Equal(dict, items);
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
public static void TestDebuggerAttributes_Null()
{
Type proxyType = DebuggerAttributes.GetProxyType(ImmutableHashSet.Create<string>());
TargetInvocationException tie = Assert.Throws<TargetInvocationException>(() => Activator.CreateInstance(proxyType, (object)null));
Assert.IsType<ArgumentNullException>(tie.InnerException);
}

[Fact]
public void Clear_NoComparer_ReturnsEmptyWithoutComparer()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,27 +255,6 @@ public void GetValueOrDefaultOfConcreteType()
Assert.Equal(5, populated.GetValueOrDefault("a", 1));
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
public void DebuggerAttributesValid()
{
DebuggerAttributes.ValidateDebuggerDisplayReferences(ImmutableSortedDictionary.CreateBuilder<string, int>());
ImmutableSortedDictionary<int, string>.Builder builder = ImmutableSortedDictionary.CreateBuilder<int, string>();
builder.Add(1, "One");
builder.Add(2, "Two");
DebuggerAttributeInfo info = DebuggerAttributes.ValidateDebuggerTypeProxyProperties(builder);
PropertyInfo itemProperty = info.Properties.Single(pr => pr.GetCustomAttribute<DebuggerBrowsableAttribute>().State == DebuggerBrowsableState.RootHidden);
KeyValuePair<int, string>[] items = itemProperty.GetValue(info.Instance) as KeyValuePair<int, string>[];
Assert.Equal(builder, items);
}

[ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsDebuggerTypeProxyAttributeSupported))]
public static void TestDebuggerAttributes_Null()
{
Type proxyType = DebuggerAttributes.GetProxyType(ImmutableSortedDictionary.CreateBuilder<int, string>());
TargetInvocationException tie = Assert.Throws<TargetInvocationException>(() => Activator.CreateInstance(proxyType, (object)null));
Assert.IsType<ArgumentNullException>(tie.InnerException);
}

[Fact]
public void ValueRef()
{
Expand Down
Loading
Loading