Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
Original file line number Diff line number Diff line change
Expand Up @@ -307,15 +307,13 @@ private static
/// </summary>
/// <param name="path">The path of the assembly.</param>
/// <returns>The loaded <see cref="Assembly"/>.</returns>
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:Members attributed with RequiresUnreferencedCode may break when trimming", Justification = "AssemblyResolver is part of the legacy reflection-mode loader and is not used in source-generator / Native AOT execution mode.")]
#if NETFRAMEWORK
protected virtual
#else
private static
#endif
// This whole class is not used in source generator mode.
#pragma warning disable IL2026 // Members attributed with RequiresUnreferencedCode may break when trimming
Assembly LoadAssemblyFrom(string path) => Assembly.LoadFrom(path);
#pragma warning restore IL2026 // Members attributed with RequiresUnreferencedCode may break when trimming

#if NETFRAMEWORK
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,8 @@ private static void InferGenerics(Type parameterType, Type argumentType, List<(T
//
// [DataRow(0, "Hello")]
// public void TestMethod<T1, T2>(T2 p0, T1, p1) { }
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060:Call to 'System.Reflection.MethodInfo.MakeGenericMethod' can not be statically analyzed.", Justification = "Generic test methods with substituted type arguments are part of MSTest's reflection-mode adapter. Native AOT support relies on MSTest source-generated metadata, not on this code path.")]
[UnconditionalSuppressMessage("Aot", "IL3050:Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT", Justification = "Generic test methods with substituted type arguments are part of MSTest's reflection-mode adapter. Native AOT support relies on MSTest source-generated metadata, not on this code path.")]
private static MethodInfo ConstructGenericMethod(MethodInfo methodInfo, object?[]? arguments)
{
DebugEx.Assert(methodInfo.IsGenericMethod, "ConstructGenericMethod should only be called for a generic method.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ namespace Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Helpers;

internal static class DataSerializationHelper
{
private const string DataContractSerializationJustification =
"Data contract serialization is used for cross-process VSTest payloads. " +
"This should be safe as long as our generator mentions getting fields / properties of the target type. " +
"https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551";

private static readonly ConcurrentDictionary<string, DataContractJsonSerializer> SerializerCache = new();
private static readonly DataContractJsonSerializerSettings SerializerSettings = new()
{
Expand All @@ -30,6 +35,8 @@ internal static class DataSerializationHelper
/// </summary>
/// <param name="data">Data array to serialize.</param>
/// <returns>Serialized array.</returns>
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:Members attributed with RequiresUnreferencedCode may break when trimming", Justification = DataContractSerializationJustification)]
[UnconditionalSuppressMessage("Aot", "IL3050:Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT", Justification = DataContractSerializationJustification)]
public static string?[]? Serialize(object?[]? data)
{
if (data == null)
Expand Down Expand Up @@ -61,14 +68,7 @@ internal static class DataSerializationHelper
#endif

using var memoryStream = new MemoryStream();
// This should be safe as long as our generator mentions
// getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551
// Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other.
#pragma warning disable IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT
#pragma warning disable IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming
serializer.WriteObject(memoryStream, data[i]);
#pragma warning restore IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT
#pragma warning restore IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming
byte[] serializerData = memoryStream.ToArray();

serializedData[dataIndex] = Encoding.UTF8.GetString(serializerData, 0, serializerData.Length);
Expand All @@ -82,6 +82,8 @@ internal static class DataSerializationHelper
/// </summary>
/// <param name="serializedData">Serialized data array to deserialize.</param>
/// <returns>Deserialized array.</returns>
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:Members attributed with RequiresUnreferencedCode may break when trimming", Justification = DataContractSerializationJustification)]
[UnconditionalSuppressMessage("Aot", "IL3050:Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT", Justification = DataContractSerializationJustification)]
public static object?[]? Deserialize(string?[]? serializedData)
{
if (serializedData == null || serializedData.Length % 2 != 0)
Expand Down Expand Up @@ -111,14 +113,7 @@ internal static class DataSerializationHelper

byte[] serializedDataBytes = Encoding.UTF8.GetBytes(serializedValue);
using var memoryStream = new MemoryStream(serializedDataBytes);
// This should be safe as long as our generator mentions
// getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551
// Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other.
#pragma warning disable IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT
#pragma warning disable IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming
data[i] = serializer.ReadObject(memoryStream);
#pragma warning restore IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT
#pragma warning restore IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming
// For some reason, we don't get SerializationSurrogateProvider.GetDeserializedObject to be called by .NET runtime.
// So we manually call it.
data[i] = SerializationSurrogateProvider.GetDeserializedObject(data[i]!);
Expand All @@ -128,26 +123,20 @@ internal static class DataSerializationHelper
}

private static DataContractJsonSerializer GetSerializer(string assemblyQualifiedName)
=> SerializerCache.GetOrAdd(
assemblyQualifiedName,
// This should be safe as long as our generator mentions
// getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551
// Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other.
#pragma warning disable IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT
#pragma warning disable IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming
_ => new DataContractJsonSerializer(PlatformServiceProvider.Instance.ReflectionOperations.GetType(assemblyQualifiedName) ?? typeof(object), SerializerSettings));
#pragma warning restore IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT
#pragma warning restore IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming
=> SerializerCache.GetOrAdd(assemblyQualifiedName, CreateSerializerForAssemblyQualifiedName);

private static DataContractJsonSerializer GetSerializer(Type type)
=> SerializerCache.GetOrAdd(
type.AssemblyQualifiedName!,
// This should be safe as long as our generator mentions
// getting fields / properties of the target type. https://github.com/dotnet/runtime/issues/71350#issuecomment-1168140551
// Not the best solution, maybe we can replace this with System.Text.Json, but the we need one generator calling the other.
#pragma warning disable IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT
#pragma warning disable IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming
_ => new DataContractJsonSerializer(type, SerializerSettings));
=> SerializerCache.GetOrAdd(type.AssemblyQualifiedName!, _ => CreateSerializerForType(type));

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:Members attributed with RequiresUnreferencedCode may break when trimming", Justification = DataContractSerializationJustification)]
[UnconditionalSuppressMessage("Aot", "IL3050:Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT", Justification = DataContractSerializationJustification)]
private static DataContractJsonSerializer CreateSerializerForAssemblyQualifiedName(string assemblyQualifiedName)
=> new(PlatformServiceProvider.Instance.ReflectionOperations.GetType(assemblyQualifiedName) ?? typeof(object), SerializerSettings);

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:Members attributed with RequiresUnreferencedCode may break when trimming", Justification = DataContractSerializationJustification)]
[UnconditionalSuppressMessage("Aot", "IL3050:Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT", Justification = DataContractSerializationJustification)]
private static DataContractJsonSerializer CreateSerializerForType(Type type)
=> new(type, SerializerSettings);

[DataContract]
private sealed class SurrogatedDateOnly
Expand Down Expand Up @@ -235,6 +224,4 @@ public Type GetSurrogateType(Type type)
return type;
}
}
#pragma warning restore IL3050 // IL3050: Avoid calling members annotated with 'RequiresDynamicCodeAttribute' when publishing as Native AOT
#pragma warning restore IL2026 // IL2026: Members attributed with RequiresUnreferencedCode may break when trimming
}
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ public static void GetManagedNameAndHierarchy(MethodBase method, out string mana
/// More information about <paramref name="managedTypeName"/> and <paramref name="managedMethodName"/> can be found in
/// <see href="https://github.com/microsoft/vstest/blob/main/docs/RFCs/0017-Managed-TestCase-Properties.md">the RFC</see>.
/// </remarks>
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:Members attributed with RequiresUnreferencedCode may break when trimming", Justification = "Reflection-based name resolution is used by the legacy VSTest bridge for managed-name lookup. Native AOT support relies on MSTest source-generated reflection metadata, not on this code path.")]
public static MethodInfo GetMethod(Assembly assembly, string managedTypeName, string managedMethodName)
{
Type type = assembly.GetType(managedTypeName, throwOnError: false, ignoreCase: false)
Expand All @@ -128,6 +129,7 @@ public static MethodInfo GetMethod(Assembly assembly, string managedTypeName, st
return method ?? throw new InvalidManagedNameException();
}

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method.", Justification = "Reflection-based name resolution is used by the legacy VSTest bridge for managed-name lookup. Native AOT support relies on MSTest source-generated reflection metadata, not on this code path.")]
private static MethodInfo? FindMethod(Type type, string methodName, int methodArity, string[]? parameterTypes)
{
bool Filter(MemberInfo mbr, object? param)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,47 +48,50 @@ internal sealed class ReflectionOperations : MarshalByRefObject, IReflectionOper
public object[] GetCustomAttributes(Assembly assembly, Type type)
=> assembly.GetCustomAttributes(type, inherit: true);

#pragma warning disable IL2070 // this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to 'target method'.
#pragma warning disable IL2026 // Members attributed with RequiresUnreferencedCode may break when trimming
#pragma warning disable IL2067 // 'target parameter' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to 'target method'.
#pragma warning disable IL2057 // Unrecognized value passed to the typeName parameter of 'System.Type.GetType(String)'
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method.", Justification = "Reflection-based discovery/execution is the MSTest reflection-mode adapter path. Native AOT support relies on MSTest source-generated reflection metadata, not on this code path.")]
public ConstructorInfo[] GetDeclaredConstructors(Type classType)
=> classType.GetConstructors(DeclaredOnlyLookup);

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method.", Justification = "Reflection-based discovery/execution is the MSTest reflection-mode adapter path. Native AOT support relies on MSTest source-generated reflection metadata, not on this code path.")]
public MethodInfo[] GetDeclaredMethods(Type classType)
=> classType.GetMethods(DeclaredOnlyLookup);

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method.", Justification = "Reflection-based discovery/execution is the MSTest reflection-mode adapter path. Native AOT support relies on MSTest source-generated reflection metadata, not on this code path.")]
public PropertyInfo[] GetDeclaredProperties(Type type)
=> type.GetProperties(DeclaredOnlyLookup);

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:Members attributed with RequiresUnreferencedCode may break when trimming", Justification = "Reflection-based discovery/execution is the MSTest reflection-mode adapter path. Native AOT support relies on MSTest source-generated reflection metadata, not on this code path.")]
public Type[] GetDefinedTypes(Assembly assembly)
=> assembly.GetTypes();

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method.", Justification = "Reflection-based discovery/execution is the MSTest reflection-mode adapter path. Native AOT support relies on MSTest source-generated reflection metadata, not on this code path.")]
public MethodInfo[] GetRuntimeMethods(Type type)
=> type.GetMethods(Everything);

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method.", Justification = "Reflection-based discovery/execution is the MSTest reflection-mode adapter path. Native AOT support relies on MSTest source-generated reflection metadata, not on this code path.")]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:'target parameter' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method.", Justification = "Reflection-based discovery/execution is the MSTest reflection-mode adapter path. Native AOT support relies on MSTest source-generated reflection metadata, not on this code path.")]
public MethodInfo? GetRuntimeMethod(Type declaringType, string methodName, Type[] parameters, bool includeNonPublic)
=> includeNonPublic
? declaringType.GetMethod(methodName, Everything, null, parameters, null)
: declaringType.GetMethod(methodName, parameters);

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:'this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method.", Justification = "Reflection-based discovery/execution is the MSTest reflection-mode adapter path. Native AOT support relies on MSTest source-generated reflection metadata, not on this code path.")]
public PropertyInfo? GetRuntimeProperty(Type classType, string testContextPropertyName, bool includeNonPublic)
=> includeNonPublic
? classType.GetProperty(testContextPropertyName, Everything)
: classType.GetProperty(testContextPropertyName);

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2057:Unrecognized value passed to the typeName parameter of 'System.Type.GetType(String)'.", Justification = "Reflection-based discovery/execution is the MSTest reflection-mode adapter path. Native AOT support relies on MSTest source-generated reflection metadata, not on this code path.")]
public Type? GetType(string typeName)
=> Type.GetType(typeName);

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:Members attributed with RequiresUnreferencedCode may break when trimming", Justification = "Reflection-based discovery/execution is the MSTest reflection-mode adapter path. Native AOT support relies on MSTest source-generated reflection metadata, not on this code path.")]
public Type? GetType(Assembly assembly, string typeName)
=> assembly.GetType(typeName);

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2067:'target parameter' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to target method.", Justification = "Reflection-based discovery/execution is the MSTest reflection-mode adapter path. Native AOT support relies on MSTest source-generated reflection metadata, not on this code path.")]
public object? CreateInstance(Type type, object?[] parameters)
=> Activator.CreateInstance(type, parameters);
#pragma warning restore IL2070 // this' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to 'target method'.
#pragma warning restore IL2026 // Members attributed with RequiresUnreferencedCode may break when trimming
#pragma warning restore IL2067 // 'target parameter' argument does not satisfy 'DynamicallyAccessedMembersAttribute' in call to 'target method'.
#pragma warning restore IL2057 // Unrecognized value passed to the typeName parameter of 'System.Type.GetType(String)'

/// <summary>
/// Checks to see if a member or type is decorated with the given attribute, or an attribute that derives from it. e.g. [MyTestClass] from [TestClass] will match if you look for [TestClass]. The inherit parameter does not impact this checking.
Expand Down
Loading