Skip to content

Commit

Permalink
Add trimming/AOT annotations (#266)
Browse files Browse the repository at this point in the history
  • Loading branch information
sbomer authored Oct 17, 2024
1 parent 1d123c1 commit 0e726b6
Show file tree
Hide file tree
Showing 8 changed files with 222 additions and 2 deletions.
11 changes: 11 additions & 0 deletions src/AmqpEventSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace Microsoft.Azure.Amqp
{
using System;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Tracing;

[EventSource(Name = "Microsoft-Azure-Amqp")]
Expand All @@ -15,6 +16,8 @@ sealed class AmqpEventSource : EventSource
// 3. When changing the event definition, update callers in AmqpTrace
// if needed.

private const string EventSourceSuppressMessage = "Parameters to this method are primitive and are trimmer safe.";

public static readonly AmqpEventSource Log;

static AmqpEventSource()
Expand All @@ -23,6 +26,7 @@ static AmqpEventSource()
}

[Event(1, Level = EventLevel.Informational, Message = "{0}: open connection {1}.")]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = EventSourceSuppressMessage)]
public unsafe void AmqpOpenConnection(string source, string connection)
{
fixed (char* ptrSource = source)
Expand Down Expand Up @@ -440,6 +444,7 @@ public unsafe void AmqpSentMessage(string source, uint deliveryId, long bytes)
}

[NonEvent]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = EventSourceSuppressMessage)]
unsafe void WriteEvent(int eventId, IntPtr a1, int size1, IntPtr a2, int size2)
{
EventSource.EventData* descrs = stackalloc EventSource.EventData[2];
Expand All @@ -451,6 +456,7 @@ unsafe void WriteEvent(int eventId, IntPtr a1, int size1, IntPtr a2, int size2)
}

[NonEvent]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = EventSourceSuppressMessage)]
unsafe void WriteEvent(int eventId, IntPtr a1, int size1, IntPtr a2, int size2, IntPtr a3, int size3)
{
EventSource.EventData* descrs = stackalloc EventSource.EventData[3];
Expand All @@ -464,6 +470,7 @@ unsafe void WriteEvent(int eventId, IntPtr a1, int size1, IntPtr a2, int size2,
}

[NonEvent]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = EventSourceSuppressMessage)]
unsafe void WriteEvent(int eventId, IntPtr a1, int size1, IntPtr a2, int size2,
IntPtr a3, int size3, IntPtr a4, int size4)
{
Expand All @@ -480,6 +487,7 @@ unsafe void WriteEvent(int eventId, IntPtr a1, int size1, IntPtr a2, int size2,
}

[NonEvent]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = EventSourceSuppressMessage)]
unsafe void WriteEvent(int eventId, IntPtr a1, int size1, IntPtr a2, int size2,
IntPtr a3, int size3, IntPtr a4, int size4, IntPtr a5, int size5)
{
Expand All @@ -498,6 +506,7 @@ unsafe void WriteEvent(int eventId, IntPtr a1, int size1, IntPtr a2, int size2,
}

[NonEvent]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = EventSourceSuppressMessage)]
unsafe void WriteEvent(int eventId, IntPtr a1, int size1, IntPtr a2, int size2,
IntPtr a3, int size3, IntPtr a4, int size4, IntPtr a5, int size5, IntPtr a6, int size6)
{
Expand All @@ -518,6 +527,7 @@ unsafe void WriteEvent(int eventId, IntPtr a1, int size1, IntPtr a2, int size2,
}

[NonEvent]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = EventSourceSuppressMessage)]
unsafe void WriteEvent(int eventId, IntPtr a1, int size1, IntPtr a2, int size2,
IntPtr a3, int size3, IntPtr a4, int size4, IntPtr a5, int size5, IntPtr a6, int size6,
IntPtr a7, int size7)
Expand All @@ -541,6 +551,7 @@ unsafe void WriteEvent(int eventId, IntPtr a1, int size1, IntPtr a2, int size2,
}

[NonEvent]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026", Justification = EventSourceSuppressMessage)]
unsafe void WriteEvent(int eventId, IntPtr a1, int size1, IntPtr a2, int size2,
IntPtr a3, int size3, IntPtr a4, int size4, IntPtr a5, int size5, IntPtr a6, int size6,
IntPtr a7, int size7, IntPtr a8, int size8)
Expand Down
6 changes: 4 additions & 2 deletions src/Microsoft.Azure.Amqp.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Description>Microsoft.Azure.Amqp Class Library</Description>
Expand All @@ -22,7 +22,9 @@
<GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute>
<Configurations>Debug;Release;Signed</Configurations>
<GeneratePackageOnBuild>false</GeneratePackageOnBuild>
<LangVersion>9</LangVersion>
<LangVersion>10</LangVersion>
<IsTrimmable Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net6.0'))">true</IsTrimmable>
<IsAotCompatible Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net7.0'))">true</IsAotCompatible>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
Expand Down
24 changes: 24 additions & 0 deletions src/Serialization/AmqpContractSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace Microsoft.Azure.Amqp.Serialization
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
Expand All @@ -18,6 +19,9 @@ namespace Microsoft.Azure.Amqp.Serialization
/// </summary>
public sealed class AmqpContractSerializer
{
internal const string TrimWarning = "AmqpContractSerializer relies on reflection-based serialization. Required types may be removed when trimming.";
internal const string AotWarning = "AmqpContractSerializer relies on dynamically creating types that may not be available with Ahead of Time compilation.";

static readonly Dictionary<Type, SerializableType> builtInTypes = new Dictionary<Type, SerializableType>()
{
{ typeof(bool), SerializableType.CreatePrimitiveType(typeof(bool)) },
Expand Down Expand Up @@ -91,6 +95,8 @@ public AmqpContractSerializer(Func<Type, SerializableType> compiler)
/// </summary>
/// <param name="stream">The destination stream.</param>
/// <param name="graph">The object to serialize.</param>
[RequiresUnreferencedCode(TrimWarning)]
[RequiresDynamicCode(AotWarning)]
public static void WriteObject(Stream stream, object graph)
{
if (graph == null)
Expand All @@ -114,6 +120,8 @@ public static void WriteObject(Stream stream, object graph)
/// <typeparam name="T">The expected type.</typeparam>
/// <param name="stream">The source stream.</param>
/// <returns>An object of T.</returns>
[RequiresUnreferencedCode(TrimWarning)]
[RequiresDynamicCode(AotWarning)]
public static T ReadObject<T>(Stream stream)
{
return ReadObject<T, T>(stream);
Expand All @@ -128,6 +136,8 @@ public static T ReadObject<T>(Stream stream)
/// <returns>An object of TAs.</returns>
/// <remarks>The serializer uses T to resolve decoding
/// types and returns the decoded object as TAs.</remarks>
[RequiresUnreferencedCode(TrimWarning)]
[RequiresDynamicCode(AotWarning)]
public static TAs ReadObject<T, TAs>(Stream stream)
{
if (!stream.CanSeek)
Expand Down Expand Up @@ -168,6 +178,8 @@ public static TAs ReadObject<T, TAs>(Stream stream)
/// </summary>
/// <param name="buffer"></param>
/// <param name="graph"></param>
[RequiresUnreferencedCode(TrimWarning)]
[RequiresDynamicCode(AotWarning)]
public void WriteObjectToBuffer(ByteBuffer buffer, object graph)
{
if (graph == null)
Expand All @@ -187,6 +199,8 @@ public void WriteObjectToBuffer(ByteBuffer buffer, object graph)
/// <typeparam name="T">The expected type.</typeparam>
/// <param name="buffer">The source buffer.</param>
/// <returns>An object of T.</returns>
[RequiresUnreferencedCode(TrimWarning)]
[RequiresDynamicCode(AotWarning)]
public T ReadObjectFromBuffer<T>(ByteBuffer buffer)
{
return this.ReadObjectFromBuffer<T, T>(buffer);
Expand All @@ -201,12 +215,16 @@ public T ReadObjectFromBuffer<T>(ByteBuffer buffer)
/// <returns>An object of TAs.</returns>
/// <remarks>The serializer uses T to resolve decoding
/// types and returns the decoded object as TAs.</remarks>
[RequiresUnreferencedCode(TrimWarning)]
[RequiresDynamicCode(AotWarning)]
public TAs ReadObjectFromBuffer<T, TAs>(ByteBuffer buffer)
{
SerializableType type = this.GetType(typeof(T));
return (TAs)type.ReadObject(buffer);
}

[RequiresUnreferencedCode(TrimWarning)]
[RequiresDynamicCode(AotWarning)]
internal SerializableType GetType(Type type)
{
return this.GetOrCompileType(type, false);
Expand All @@ -227,6 +245,8 @@ bool TryGetSerializableType(Type type, out SerializableType serializableType)
return false;
}

[RequiresUnreferencedCode(TrimWarning)]
[RequiresDynamicCode(AotWarning)]
SerializableType GetOrCompileType(Type type, bool describedOnly)
{
SerializableType serialiableType = null;
Expand All @@ -247,6 +267,8 @@ SerializableType GetOrCompileType(Type type, bool describedOnly)
return serialiableType;
}

[RequiresUnreferencedCode(TrimWarning)]
[RequiresDynamicCode(AotWarning)]
SerializableType CompileType(Type type, bool describedOnly)
{
if (this.externalCompilers != null)
Expand Down Expand Up @@ -395,6 +417,8 @@ SerializableType CompileType(Type type, bool describedOnly)
}
}

[RequiresUnreferencedCode(TrimWarning)]
[RequiresDynamicCode(AotWarning)]
SerializableType CompileNonContractTypes(Type type)
{
if (type.GetTypeInfo().IsGenericType &&
Expand Down
6 changes: 6 additions & 0 deletions src/Serialization/MemberAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace Microsoft.Azure.Amqp.Serialization
{
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;

abstract class MemberAccessor
Expand All @@ -22,6 +23,8 @@ public Type Type
get { return this.type; }
}

[RequiresUnreferencedCode(AmqpContractSerializer.TrimWarning)]
[RequiresDynamicCode(AmqpContractSerializer.AotWarning)]
public static MemberAccessor Create(MemberInfo memberInfo, bool requiresSetter)
{
FieldInfo fieldInfo;
Expand All @@ -48,6 +51,7 @@ public void Set(object container, object value)
this.setter(container, value);
}

[RequiresUnreferencedCode(AmqpContractSerializer.TrimWarning)]
sealed class FieldMemberAccessor : MemberAccessor
{
public FieldMemberAccessor(FieldInfo fieldInfo)
Expand All @@ -58,6 +62,8 @@ public FieldMemberAccessor(FieldInfo fieldInfo)
}
}

[RequiresUnreferencedCode(AmqpContractSerializer.TrimWarning)]
[RequiresDynamicCode(AmqpContractSerializer.AotWarning)]
sealed class PropertyMemberAccessor : MemberAccessor
{
public PropertyMemberAccessor(PropertyInfo propertyInfo, bool requiresSetter)
Expand Down
3 changes: 3 additions & 0 deletions src/Serialization/MethodAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace Microsoft.Azure.Amqp.Serialization
{
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;

delegate object MethodDelegate(object container, object[] parameters);
Expand All @@ -13,6 +14,7 @@ abstract class MethodAccessor
bool isStatic;
MethodDelegate methodDelegate;

[RequiresDynamicCode(AmqpContractSerializer.AotWarning)]
public static MethodAccessor Create(MethodInfo methodInfo)
{
return new TypeMethodAccessor(methodInfo);
Expand Down Expand Up @@ -54,6 +56,7 @@ public ConstructorAccessor(ConstructorInfo constructorInfo)

sealed class TypeMethodAccessor : MethodAccessor
{
[RequiresDynamicCode(AmqpContractSerializer.AotWarning)]
public TypeMethodAccessor(MethodInfo methodInfo)
{
this.isStatic = methodInfo.IsStatic;
Expand Down
4 changes: 4 additions & 0 deletions src/Serialization/ReflectionExtentions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace Microsoft.Azure.Amqp.Serialization
{
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.Serialization;

Expand All @@ -25,6 +26,7 @@ public static Action<object, object> CreateSetter(this FieldInfo fieldInfo)
return (obj, val) => fieldInfo.SetValue(obj, val);
}

[RequiresDynamicCode(AmqpContractSerializer.AotWarning)]
public static Func<object, object> CreateGetter(this PropertyInfo propertyInfo)
{
MethodInfo getMethod = propertyInfo.GetGetMethod(true);
Expand All @@ -33,6 +35,7 @@ public static Func<object, object> CreateGetter(this PropertyInfo propertyInfo)
return (Func<object, object>)m2.Invoke(null, new object[] { getMethod });
}

[RequiresDynamicCode(AmqpContractSerializer.AotWarning)]
public static Action<object, object> CreateSetter(this PropertyInfo propertyInfo, bool requiresSetter)
{
if (requiresSetter && propertyInfo.DeclaringType.IsValueType)
Expand Down Expand Up @@ -63,6 +66,7 @@ public static MethodDelegate CreateMethod(this ConstructorInfo constructorInfo)
throw new NotImplementedException();
}

[RequiresDynamicCode(AmqpContractSerializer.AotWarning)]
public static MethodDelegate CreateMethod(this MethodInfo methodInfo, bool isStatic)
{
var parameters = methodInfo.GetParameters();
Expand Down
11 changes: 11 additions & 0 deletions src/Serialization/SerializableType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ namespace Microsoft.Azure.Amqp.Serialization
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.Serialization;
using Microsoft.Azure.Amqp.Encoding;
Expand Down Expand Up @@ -299,6 +300,8 @@ public override object ReadObject(ByteBuffer buffer)
}
}

[RequiresUnreferencedCode(AmqpContractSerializer.TrimWarning)]
[RequiresDynamicCode(AmqpContractSerializer.AotWarning)]
internal sealed class List : Collection
{
readonly SerializableType itemType;
Expand Down Expand Up @@ -376,6 +379,8 @@ public override void ReadMembers(ByteBuffer buffer, object container, ref int co
}
}

[RequiresUnreferencedCode(AmqpContractSerializer.TrimWarning)]
[RequiresDynamicCode(AmqpContractSerializer.AotWarning)]
internal sealed class Map : Collection
{
readonly SerializableType keyType;
Expand Down Expand Up @@ -451,6 +456,8 @@ public override void ReadMembers(ByteBuffer buffer, object container, ref int co
}
}

[RequiresUnreferencedCode(AmqpContractSerializer.AotWarning)]
[RequiresDynamicCode(AmqpContractSerializer.AotWarning)]
internal abstract class Composite : Collection
{
readonly Composite baseType;
Expand Down Expand Up @@ -625,6 +632,8 @@ bool AreEqual(ulong? code1, AmqpSymbol symbol1, ulong? code2, AmqpSymbol symbol2
}
}

[RequiresUnreferencedCode(AmqpContractSerializer.AotWarning)]
[RequiresDynamicCode(AmqpContractSerializer.AotWarning)]
internal sealed class CompositeList : Composite
{
public CompositeList(
Expand Down Expand Up @@ -682,6 +691,8 @@ public override void ReadMembers(ByteBuffer buffer, object container, ref int co
}
}

[RequiresUnreferencedCode(AmqpContractSerializer.AotWarning)]
[RequiresDynamicCode(AmqpContractSerializer.AotWarning)]
internal sealed class CompositeMap : Composite
{
public CompositeMap(
Expand Down
Loading

0 comments on commit 0e726b6

Please sign in to comment.