// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.Diagnostics.CodeAnalysis;
+
namespace System.Diagnostics
{
/// <summary>
{
private Type? _target;
- public DebuggerVisualizerAttribute(string visualizerTypeName)
+ public DebuggerVisualizerAttribute(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] string visualizerTypeName)
{
VisualizerTypeName = visualizerTypeName;
}
- public DebuggerVisualizerAttribute(string visualizerTypeName, string? visualizerObjectSourceTypeName)
+ public DebuggerVisualizerAttribute(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] string visualizerTypeName,
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] string? visualizerObjectSourceTypeName)
{
VisualizerTypeName = visualizerTypeName;
VisualizerObjectSourceTypeName = visualizerObjectSourceTypeName;
}
- public DebuggerVisualizerAttribute(string visualizerTypeName, Type visualizerObjectSource)
+ public DebuggerVisualizerAttribute(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] string visualizerTypeName,
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type visualizerObjectSource)
{
if (visualizerObjectSource == null)
{
VisualizerObjectSourceTypeName = visualizerObjectSource.AssemblyQualifiedName;
}
- public DebuggerVisualizerAttribute(Type visualizer)
+ public DebuggerVisualizerAttribute(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type visualizer)
{
if (visualizer == null)
{
VisualizerTypeName = visualizer.AssemblyQualifiedName!;
}
- public DebuggerVisualizerAttribute(Type visualizer, Type visualizerObjectSource)
+ public DebuggerVisualizerAttribute(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type visualizer,
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type visualizerObjectSource)
{
if (visualizer == null)
{
VisualizerObjectSourceTypeName = visualizerObjectSource.AssemblyQualifiedName;
}
- public DebuggerVisualizerAttribute(Type visualizer, string? visualizerObjectSourceTypeName)
+ public DebuggerVisualizerAttribute(
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type visualizer,
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] string? visualizerObjectSourceTypeName)
{
if (visualizer == null)
{
VisualizerObjectSourceTypeName = visualizerObjectSourceTypeName;
}
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
public string? VisualizerObjectSourceTypeName { get; }
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
public string VisualizerTypeName { get; }
public string? Description { get; set; }
[System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Struct, AllowMultiple=true)]
public sealed partial class DebuggerVisualizerAttribute : System.Attribute
{
- public DebuggerVisualizerAttribute(string visualizerTypeName) { }
- public DebuggerVisualizerAttribute(string visualizerTypeName, string? visualizerObjectSourceTypeName) { }
- public DebuggerVisualizerAttribute(string visualizerTypeName, System.Type visualizerObjectSource) { }
- public DebuggerVisualizerAttribute(System.Type visualizer) { }
- public DebuggerVisualizerAttribute(System.Type visualizer, string? visualizerObjectSourceTypeName) { }
- public DebuggerVisualizerAttribute(System.Type visualizer, System.Type visualizerObjectSource) { }
+ public DebuggerVisualizerAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] string visualizerTypeName) { }
+ public DebuggerVisualizerAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] string visualizerTypeName, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] string? visualizerObjectSourceTypeName) { }
+ public DebuggerVisualizerAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] string visualizerTypeName, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type visualizerObjectSource) { }
+ public DebuggerVisualizerAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type visualizer) { }
+ public DebuggerVisualizerAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type visualizer, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] string? visualizerObjectSourceTypeName) { }
+ public DebuggerVisualizerAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type visualizer, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type visualizerObjectSource) { }
public string? Description { get { throw null; } set { } }
public System.Type? Target { get { throw null; } set { } }
public string? TargetTypeName { get { throw null; } set { } }
+ [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)]
public string? VisualizerObjectSourceTypeName { get { throw null; } }
+ [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)]
public string VisualizerTypeName { get { throw null; } }
}
[System.AttributeUsage(AttributeTargets.Class | System.AttributeTargets.Method | System.AttributeTargets.Constructor | System.AttributeTargets.Struct, Inherited = false)]
--- /dev/null
+using System;
+using System.Diagnostics;
+
+/// <summary>
+/// Tests that types used by DebuggerVisualizerAttribute are not trimmed out
+/// when Debugger.IsSupported is true (the default).
+/// </summary>
+class Program
+{
+ static int Main(string[] args)
+ {
+ MyClass myClass = new MyClass() { Name = "trimmed" };
+ MyClassWithVisualizerString myClassWithString = new MyClassWithVisualizerString() { Name = "trimmed" };
+
+ Type[] allTypes = typeof(MyClass).Assembly.GetTypes();
+ bool foundDebuggerVisualizer = false;
+ bool foundDebuggerVisualizer2 = false;
+ bool foundDebuggerVisualizerObjectSource = false;
+ bool foundStringDebuggerVisualizer = false;
+ bool foundStringDebuggerVisualizer2 = false;
+ bool foundStringDebuggerVisualizerObjectSource = false;
+ for (int i = 0; i < allTypes.Length; i++)
+ {
+ Type currentType = allTypes[i];
+ if (currentType.FullName == "Program+MyClass+DebuggerVisualizer" &&
+ currentType.GetProperties().Length == 1 &&
+ currentType.GetConstructors().Length == 1)
+ {
+ foundDebuggerVisualizer = true;
+ }
+ else if (currentType.FullName == "Program+MyClass+DebuggerVisualizer2" &&
+ currentType.GetProperties().Length == 1 &&
+ currentType.GetConstructors().Length == 1)
+ {
+ foundDebuggerVisualizer2 = true;
+ }
+ else if (currentType.FullName == "Program+MyClass+DebuggerVisualizerObjectSource" &&
+ currentType.GetProperties().Length == 1 &&
+ currentType.GetConstructors().Length == 1)
+ {
+ foundDebuggerVisualizerObjectSource = true;
+ }
+ else if (currentType.FullName == "Program+MyClassWithVisualizerStringVisualizer" &&
+ currentType.GetProperties().Length == 1 &&
+ currentType.GetConstructors().Length == 1)
+ {
+ foundStringDebuggerVisualizer = true;
+ }
+ else if (currentType.FullName == "Program+MyClassWithVisualizerStringVisualizer2" &&
+ currentType.GetProperties().Length == 1 &&
+ currentType.GetConstructors().Length == 1)
+ {
+ foundStringDebuggerVisualizer2 = true;
+ }
+ else if (currentType.FullName == "Program+MyClassWithVisualizerStringVisualizerObjectSource" &&
+ currentType.GetProperties().Length == 1 &&
+ currentType.GetConstructors().Length == 1)
+ {
+ foundStringDebuggerVisualizerObjectSource = true;
+ }
+ }
+
+ if (!foundDebuggerVisualizer) return -1;
+ if (!foundDebuggerVisualizer2) return -2;
+ if (!foundDebuggerVisualizerObjectSource) return -3;
+ if (!foundStringDebuggerVisualizer) return -4;
+ if (!foundStringDebuggerVisualizer2) return -5;
+ if (!foundStringDebuggerVisualizerObjectSource) return -6;
+
+ return 100;
+ }
+
+ [DebuggerVisualizer(typeof(DebuggerVisualizer))]
+ [DebuggerVisualizer(typeof(DebuggerVisualizer2), typeof(DebuggerVisualizerObjectSource))]
+ public class MyClass
+ {
+ public string Name { get; set; }
+
+ private class DebuggerVisualizer
+ {
+ private MyClass _instance;
+
+ public DebuggerVisualizer(MyClass instance)
+ {
+ _instance = instance;
+ }
+
+ public string DebuggerName => _instance.Name + " Visualizer";
+ }
+
+ private class DebuggerVisualizer2
+ {
+ private MyClass _instance;
+
+ public DebuggerVisualizer2(MyClass instance)
+ {
+ _instance = instance;
+ }
+
+ public string DebuggerName => _instance.Name + " Visualizer";
+ }
+
+ private class DebuggerVisualizerObjectSource
+ {
+ private MyClass _instance;
+
+ public DebuggerVisualizerObjectSource(MyClass instance)
+ {
+ _instance = instance;
+ }
+
+ public string DebuggerName => _instance.Name + " Visualizer";
+ }
+ }
+
+ [DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer")]
+ [DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer2", "Program+MyClassWithVisualizerStringVisualizerObjectSource")]
+ public class MyClassWithVisualizerString
+ {
+ public string Name { get; set; }
+ }
+
+ internal class MyClassWithVisualizerStringVisualizer
+ {
+ private MyClassWithVisualizerString _instance;
+
+ public MyClassWithVisualizerStringVisualizer(MyClassWithVisualizerString instance)
+ {
+ _instance = instance;
+ }
+
+ public string DebuggerName => _instance.Name + " StringVisualizer";
+ }
+
+ internal class MyClassWithVisualizerStringVisualizer2
+ {
+ private MyClassWithVisualizerString _instance;
+
+ public MyClassWithVisualizerStringVisualizer2(MyClassWithVisualizerString instance)
+ {
+ _instance = instance;
+ }
+
+ public string DebuggerName => _instance.Name + " StringVisualizer";
+ }
+
+ internal class MyClassWithVisualizerStringVisualizerObjectSource
+ {
+ private MyClassWithVisualizerString _instance;
+
+ public MyClassWithVisualizerStringVisualizerObjectSource(MyClassWithVisualizerString instance)
+ {
+ _instance = instance;
+ }
+
+ public string DebuggerName => _instance.Name + " StringVisualizer";
+ }
+}
<SkipOnTestRuntimes>osx-x64;linux-x64;browser-wasm</SkipOnTestRuntimes>
</TestConsoleAppSourceFiles>
<TestConsoleAppSourceFiles Include="DebuggerTypeProxyAttributeTests.cs" />
+ <TestConsoleAppSourceFiles Include="DebuggerVisualizerAttributeTests.cs" />
<TestConsoleAppSourceFiles Include="DefaultValueAttributeCtorTest.cs" />
<TestConsoleAppSourceFiles Include="GenericArraySortHelperTest.cs" />
<TestConsoleAppSourceFiles Include="InheritedAttributeTests.cs" />