Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
fix ILLink warnings
  • Loading branch information
eiriktsarpalis committed Jul 15, 2021
commit 2e1d4491751e14b552064f0131bbe32629ccc08b
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization.Metadata;

namespace System.Text.Json.Serialization.Converters
Expand All @@ -12,6 +13,7 @@ internal sealed class FSharpListConverter<TList, TElement> : IEnumerableDefaultC
{
private readonly Func<IEnumerable<TElement>, TList> _listConstructor;

[RequiresUnreferencedCode(FSharpCoreReflectionProxy.FSharpCoreUnreferencedCodeMessage)]
public FSharpListConverter()
{
_listConstructor = FSharpCoreReflectionProxy.Instance.CreateFSharpListConstructor<TList, TElement>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization.Metadata;

namespace System.Text.Json.Serialization.Converters
Expand All @@ -13,6 +14,7 @@ internal sealed class FSharpMapConverter<TMap, TKey, TValue> : DictionaryDefault
{
private readonly Func<IEnumerable<Tuple<TKey, TValue>>, TMap> _mapConstructor;

[RequiresUnreferencedCode(FSharpCoreReflectionProxy.FSharpCoreUnreferencedCodeMessage)]
public FSharpMapConverter()
{
_mapConstructor = FSharpCoreReflectionProxy.Instance.CreateFSharpMapConstructor<TMap, TKey, TValue>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization.Metadata;

namespace System.Text.Json.Serialization.Converters
Expand All @@ -18,6 +19,7 @@ internal sealed class FSharpOptionConverter<TOption, TElement> : JsonResumableCo
private readonly Func<TOption, TElement> _optionValueGetter;
private readonly Func<TElement, TOption> _optionConstructor;

[RequiresUnreferencedCode(FSharpCoreReflectionProxy.FSharpCoreUnreferencedCodeMessage)]
public FSharpOptionConverter(JsonConverter<TElement> elementConverter)
{
_optionValueGetter = FSharpCoreReflectionProxy.Instance.CreateFSharpOptionValueGetter<TOption, TElement>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization.Metadata;

namespace System.Text.Json.Serialization.Converters
Expand All @@ -12,6 +13,7 @@ internal sealed class FSharpSetConverter<TSet, TElement> : IEnumerableDefaultCon
{
private readonly Func<IEnumerable<TElement>, TSet> _setConstructor;

[RequiresUnreferencedCode(FSharpCoreReflectionProxy.FSharpCoreUnreferencedCodeMessage)]
public FSharpSetConverter()
{
_setConstructor = FSharpCoreReflectionProxy.Instance.CreateFSharpSetConstructor<TSet, TElement>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,24 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization.Metadata;

namespace System.Text.Json.Serialization.Converters
{
[RequiresUnreferencedCode(FSharpCoreReflectionProxy.FSharpCoreUnreferencedCodeMessage)]
internal class FSharpTypeConverterFactory : JsonConverterFactory
{
private ObjectConverterFactory? _recordConverterFactory;

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
Justification = "The ctor is marked with RequiresUnreferencedCode.")]
public override bool CanConvert(Type typeToConvert) =>
FSharpCoreReflectionProxy.IsFSharpType(typeToConvert) &&
FSharpCoreReflectionProxy.Instance.DetectFSharpKind(typeToConvert) is not FSharpKind.Unrecognized;

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
Justification = "The ctor is marked with RequiresUnreferencedCode.")]
public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
Debug.Assert(CanConvert(typeToConvert));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;

namespace System.Text.Json.Serialization.Metadata
Expand All @@ -24,6 +25,8 @@ internal enum FSharpKind
/// </summary>
internal sealed class FSharpCoreReflectionProxy
{
public const string FSharpCoreUnreferencedCodeMessage = "Uses Reflection to access FSharp.Core components, which requires unreferenced code.";

private static object s_lockObj = new object();
private static FSharpCoreReflectionProxy? s_singletonInstance;

Expand Down Expand Up @@ -80,12 +83,15 @@ public static FSharpCoreReflectionProxy Instance
}
}

[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "The public methods are marked RequiresUnreferencedCode.")]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", Justification = "The public methods are marked RequiresUnreferencedCode.")]
private FSharpCoreReflectionProxy(Assembly fsharpCoreAssembly)
{
Debug.Assert(fsharpCoreAssembly.GetName().Name == "FSharp.Core");

_compilationMappingAttributeType = fsharpCoreAssembly.GetType(CompilationMappingAttributeTypeName)!;
_sourceConstructFlagsGetter = _compilationMappingAttributeType.GetProperty("SourceConstructFlags")?.GetGetMethod();
Type compilationMappingAttributeType = fsharpCoreAssembly.GetType(CompilationMappingAttributeTypeName)!;
_sourceConstructFlagsGetter = compilationMappingAttributeType.GetMethod("get_SourceConstructFlags", BindingFlags.Public | BindingFlags.Instance);
_compilationMappingAttributeType = compilationMappingAttributeType;

_fsharpOptionType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Core.FSharpOption`1");
_fsharpListType = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.FSharpList`1");
Expand All @@ -97,6 +103,7 @@ private FSharpCoreReflectionProxy(Assembly fsharpCoreAssembly)
_fsharpMapCtor = fsharpCoreAssembly.GetType("Microsoft.FSharp.Collections.MapModule")?.GetMethod("OfSeq", BindingFlags.Public | BindingFlags.Static);
}

[RequiresUnreferencedCode(FSharpCoreUnreferencedCodeMessage)]
public FSharpKind DetectFSharpKind(Type type)
{
Attribute? compilationMappingAttribute = GetFSharpCompilationMappingAttribute(type);
Expand All @@ -122,35 +129,43 @@ public FSharpKind DetectFSharpKind(Type type)
};
}

public Func<TFSharpOption, T> CreateFSharpOptionValueGetter<TFSharpOption, T>()
[RequiresUnreferencedCode(FSharpCoreUnreferencedCodeMessage)]
public Func<TFSharpOption, T> CreateFSharpOptionValueGetter<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TFSharpOption, T>()
{
Debug.Assert(_fsharpOptionType!.MakeGenericType(typeof(T)) == typeof(TFSharpOption));
MethodInfo valueGetter = EnsureMemberExists(typeof(TFSharpOption).GetProperty("Value", BindingFlags.Public | BindingFlags.Instance)?.GetGetMethod(), "Option.Value");
Debug.Assert(typeof(TFSharpOption).GetGenericTypeDefinition() == _fsharpOptionType!);
MethodInfo valueGetter = EnsureMemberExists(typeof(TFSharpOption).GetMethod("get_Value", BindingFlags.Public | BindingFlags.Instance), "Option.Value");
return CreateDelegate<Func<TFSharpOption, T>>(valueGetter);
}

public Func<T, TFSharpOption> CreateFSharpOptionConstructor<TFSharpOption, T>()
[RequiresUnreferencedCode(FSharpCoreUnreferencedCodeMessage)]
public Func<T, TFSharpOption> CreateFSharpOptionConstructor<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] TFSharpOption, T>()
{
Debug.Assert(_fsharpOptionType!.MakeGenericType(typeof(T)) == typeof(TFSharpOption));
Debug.Assert(typeof(TFSharpOption).GetGenericTypeDefinition() == _fsharpOptionType!);
MethodInfo methodInfo = EnsureMemberExists(typeof(TFSharpOption).GetMethod("Some", BindingFlags.Public | BindingFlags.Static), "Option.Some");
return CreateDelegate<Func<T, TFSharpOption>>(methodInfo);
}

[RequiresUnreferencedCode(FSharpCoreUnreferencedCodeMessage)]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060:MakeGenericMethod", Justification = "The public methods are marked RequiresUnreferencedCode.")]
public Func<IEnumerable<T>, TFSharpList> CreateFSharpListConstructor<TFSharpList, T>()
{
Debug.Assert(_fsharpListType!.MakeGenericType(typeof(T)) == typeof(TFSharpList));
Debug.Assert(typeof(TFSharpList).GetGenericTypeDefinition() == _fsharpListType!);
return CreateDelegate<Func<IEnumerable<T>, TFSharpList>>(EnsureMemberExists(_fsharpListCtor, "List.ofSeq").MakeGenericMethod(typeof(T)));
}

[RequiresUnreferencedCode(FSharpCoreUnreferencedCodeMessage)]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060:MakeGenericMethod", Justification = "The public methods are marked RequiresUnreferencedCode.")]
public Func<IEnumerable<T>, TFSharpSet> CreateFSharpSetConstructor<TFSharpSet, T>()
{
Debug.Assert(_fsharpSetType!.MakeGenericType(typeof(T)) == typeof(TFSharpSet));
Debug.Assert(typeof(TFSharpSet).GetGenericTypeDefinition() == _fsharpSetType!);
return CreateDelegate<Func<IEnumerable<T>, TFSharpSet>>(EnsureMemberExists(_fsharpSetCtor, "Set.ofSeq").MakeGenericMethod(typeof(T)));
}

[RequiresUnreferencedCode(FSharpCoreUnreferencedCodeMessage)]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060:MakeGenericMethod", Justification = "The public methods are marked RequiresUnreferencedCode.")]
public Func<IEnumerable<Tuple<TKey, TValue>>, TFSharpMap> CreateFSharpMapConstructor<TFSharpMap, TKey, TValue>()
{
Debug.Assert(_fsharpMapType!.MakeGenericType(typeof(TKey), typeof(TValue)) == typeof(TFSharpMap));
Debug.Assert(typeof(TFSharpMap).GetGenericTypeDefinition() == _fsharpMapType!);
return CreateDelegate<Func<IEnumerable<Tuple<TKey, TValue>>, TFSharpMap>>(EnsureMemberExists(_fsharpMapCtor, "Map.ofSeq").MakeGenericMethod(typeof(TKey), typeof(TValue)));
}

Expand Down