diff --git a/eng/testing/linker/SupportFiles/Directory.Build.targets b/eng/testing/linker/SupportFiles/Directory.Build.targets index 90ce573551e90d..f1603cde43ad9d 100644 --- a/eng/testing/linker/SupportFiles/Directory.Build.targets +++ b/eng/testing/linker/SupportFiles/Directory.Build.targets @@ -19,6 +19,17 @@ + + + + + <_ManagedAssembliesToLink> + link + + + + - \ No newline at end of file + diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebuggerTypeProxyAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebuggerTypeProxyAttribute.cs index 500a946951bcff..1f99516869be62 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebuggerTypeProxyAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebuggerTypeProxyAttribute.cs @@ -1,6 +1,8 @@ // 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 { [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Assembly, AllowMultiple = true)] @@ -8,7 +10,8 @@ public sealed class DebuggerTypeProxyAttribute : Attribute { private Type? _target; - public DebuggerTypeProxyAttribute(Type type) + public DebuggerTypeProxyAttribute( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type type) { if (type == null) { @@ -18,11 +21,15 @@ public DebuggerTypeProxyAttribute(Type type) ProxyTypeName = type.AssemblyQualifiedName!; } - public DebuggerTypeProxyAttribute(string typeName) + public DebuggerTypeProxyAttribute( + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] string typeName) { ProxyTypeName = typeName; } + // The Proxy is only invoked by the debugger, so it needs to have its + // members preserved + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] public string ProxyTypeName { get; } public Type? Target diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index ee91e1dd2f824e..548f48bede5543 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -5715,8 +5715,9 @@ public DebuggerStepThroughAttribute() { } [System.AttributeUsageAttribute(System.AttributeTargets.Assembly | System.AttributeTargets.Class | System.AttributeTargets.Struct, AllowMultiple=true)] public sealed partial class DebuggerTypeProxyAttribute : System.Attribute { - public DebuggerTypeProxyAttribute(string typeName) { } - public DebuggerTypeProxyAttribute(System.Type type) { } + public DebuggerTypeProxyAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] string typeName) { } + public DebuggerTypeProxyAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type type) { } + [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] public string ProxyTypeName { get { throw null; } } public System.Type? Target { get { throw null; } set { } } public string? TargetTypeName { get { throw null; } set { } } diff --git a/src/libraries/System.Runtime/tests/TrimmingTests/DebuggerTypeProxyAttributeTests.cs b/src/libraries/System.Runtime/tests/TrimmingTests/DebuggerTypeProxyAttributeTests.cs new file mode 100644 index 00000000000000..b80f4a1d61b00b --- /dev/null +++ b/src/libraries/System.Runtime/tests/TrimmingTests/DebuggerTypeProxyAttributeTests.cs @@ -0,0 +1,73 @@ +using System; +using System.Diagnostics; + +/// +/// Tests that types used by DebuggerTypeProxyAttribute are not trimmed out +/// when Debugger.IsSupported is true (the default). +/// +class Program +{ + static int Main(string[] args) + { + MyClass myClass = new MyClass() { Name = "trimmed" }; + MyClassWithProxyString myClassWithString = new MyClassWithProxyString() { Name = "trimmed" }; + + Type[] allTypes = typeof(MyClass).Assembly.GetTypes(); + bool foundDebuggerProxy = false; + bool foundStringDebuggerProxy = false; + for (int i = 0; i < allTypes.Length; i++) + { + Type currentType = allTypes[i]; + if (currentType.FullName == "Program+MyClass+DebuggerProxy" && + currentType.GetProperties().Length == 1 && + currentType.GetConstructors().Length == 1) + { + foundDebuggerProxy = true; + } + else if (currentType.FullName == "Program+MyClassWithProxyStringProxy" && + currentType.GetProperties().Length == 1 && + currentType.GetConstructors().Length == 1) + { + foundStringDebuggerProxy = true; + } + } + + return foundDebuggerProxy && foundStringDebuggerProxy ? 100 : -1; + } + + [DebuggerTypeProxy(typeof(DebuggerProxy))] + public class MyClass + { + public string Name { get; set; } + + private class DebuggerProxy + { + private MyClass _instance; + + public DebuggerProxy(MyClass instance) + { + _instance = instance; + } + + public string DebuggerName => _instance.Name + " Proxy"; + } + } + + [DebuggerTypeProxy("Program+MyClassWithProxyStringProxy")] + public class MyClassWithProxyString + { + public string Name { get; set; } + } + + internal class MyClassWithProxyStringProxy + { + private MyClassWithProxyString _instance; + + public MyClassWithProxyStringProxy(MyClassWithProxyString instance) + { + _instance = instance; + } + + public string DebuggerName => _instance.Name + " StringProxy"; + } +} diff --git a/src/libraries/System.Runtime/tests/TrimmingTests/DefaultValueAttributeCtorTest.cs b/src/libraries/System.Runtime/tests/TrimmingTests/DefaultValueAttributeCtorTest.cs index c30fb88e0b836b..aaf82add5a0519 100644 --- a/src/libraries/System.Runtime/tests/TrimmingTests/DefaultValueAttributeCtorTest.cs +++ b/src/libraries/System.Runtime/tests/TrimmingTests/DefaultValueAttributeCtorTest.cs @@ -10,6 +10,10 @@ class Program { static int Main(string[] args) { + // workaround TypeConverterAttribute not being annotated correctly + // https://github.com/dotnet/runtime/issues/39125 + var _ = new MyStringConverter(); + TypeDescriptor.AddAttributes(typeof(string), new TypeConverterAttribute(typeof(MyStringConverter))); var attribute = new DefaultValueAttribute(typeof(string), "Hello, world!"); diff --git a/src/libraries/System.Runtime/tests/TrimmingTests/System.Runtime.TrimmingTests.proj b/src/libraries/System.Runtime/tests/TrimmingTests/System.Runtime.TrimmingTests.proj index cfd1a4d2a7b81b..ce96e07448a3cc 100644 --- a/src/libraries/System.Runtime/tests/TrimmingTests/System.Runtime.TrimmingTests.proj +++ b/src/libraries/System.Runtime/tests/TrimmingTests/System.Runtime.TrimmingTests.proj @@ -6,6 +6,8 @@ osx-x64;linux-x64 + +