From 3505cbfb8ad2347dd049dfad4701811a192f4e5f Mon Sep 17 00:00:00 2001 From: Edward Cooke Date: Sat, 30 Nov 2024 19:30:37 -0700 Subject: [PATCH] Disable fsharp on AOT/Trimming --- .../YamlDotNet.Core7AoTCompileTest.csproj | 2 + YamlDotNet/Helpers/DefaultFsharpHelper.cs | 85 +++++++++++++++++++ YamlDotNet/Helpers/FsharpHelper.cs | 52 ++---------- YamlDotNet/Helpers/IFsharpHelper.cs | 35 ++++++++ YamlDotNet/Helpers/NullFsharpHelper.cs | 42 +++++++++ .../Serialization/DeserializerBuilder.cs | 5 ++ YamlDotNet/Serialization/SerializerBuilder.cs | 5 ++ .../StaticDeserializerBuilder.cs | 1 + 8 files changed, 181 insertions(+), 46 deletions(-) create mode 100644 YamlDotNet/Helpers/DefaultFsharpHelper.cs create mode 100644 YamlDotNet/Helpers/IFsharpHelper.cs create mode 100644 YamlDotNet/Helpers/NullFsharpHelper.cs diff --git a/YamlDotNet.Core7AoTCompileTest/YamlDotNet.Core7AoTCompileTest.csproj b/YamlDotNet.Core7AoTCompileTest/YamlDotNet.Core7AoTCompileTest.csproj index aaeb2c1d..8bb0418d 100644 --- a/YamlDotNet.Core7AoTCompileTest/YamlDotNet.Core7AoTCompileTest.csproj +++ b/YamlDotNet.Core7AoTCompileTest/YamlDotNet.Core7AoTCompileTest.csproj @@ -6,6 +6,8 @@ true true enable + true + true diff --git a/YamlDotNet/Helpers/DefaultFsharpHelper.cs b/YamlDotNet/Helpers/DefaultFsharpHelper.cs new file mode 100644 index 00000000..1ab7cfe8 --- /dev/null +++ b/YamlDotNet/Helpers/DefaultFsharpHelper.cs @@ -0,0 +1,85 @@ +// This file is part of YamlDotNet - A .NET library for YAML. +// Copyright (c) Antoine Aubry and contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using YamlDotNet.Serialization; + +namespace YamlDotNet.Helpers +{ + public class DefaultFsharpHelper : IFsharpHelper + { + private static bool IsFsharpCore(Type t) + { + return t.Namespace == "Microsoft.FSharp.Core"; + } + + public bool IsOptionType(Type t) + { + return IsFsharpCore(t) && t.Name == "FSharpOption`1"; + } + + public Type? GetOptionUnderlyingType(Type t) + { + return t.IsGenericType && IsOptionType(t) ? t.GenericTypeArguments[0] : null; + } + + public object? GetValue(IObjectDescriptor objectDescriptor) + { + if (!IsOptionType(objectDescriptor.Type)) + { + throw new InvalidOperationException("Should not be called on non-Option<> type"); + } + + if (objectDescriptor.Value is null) + { + return null; + } + + return objectDescriptor.Type.GetProperty("Value").GetValue(objectDescriptor.Value); + } + + public bool IsFsharpListType(Type t) + { + return t.Namespace == "Microsoft.FSharp.Collections" && t.Name == "FSharpList`1"; + } + + public object? CreateFsharpListFromArray(Type t, Type itemsType, Array arr) + { + if (!IsFsharpListType(t)) + { + return null; + } + + var fsharpList = + t.Assembly + .GetType("Microsoft.FSharp.Collections.ListModule") + .GetMethod("OfArray") + .MakeGenericMethod(itemsType) + .Invoke(null, [arr]); + + return fsharpList; + } + } +} diff --git a/YamlDotNet/Helpers/FsharpHelper.cs b/YamlDotNet/Helpers/FsharpHelper.cs index 6339a680..8456289d 100644 --- a/YamlDotNet/Helpers/FsharpHelper.cs +++ b/YamlDotNet/Helpers/FsharpHelper.cs @@ -26,56 +26,16 @@ namespace YamlDotNet.Helpers { public static class FsharpHelper { - private static bool IsFsharpCore(Type t) - { - return t.Namespace == "Microsoft.FSharp.Core"; - } + public static IFsharpHelper? Instance { get; set; } - public static bool IsOptionType(Type t) - { - return IsFsharpCore(t) && t.Name == "FSharpOption`1"; - } + public static bool IsOptionType(Type t) => Instance?.IsOptionType(t) ?? false; - public static Type? GetOptionUnderlyingType(Type t) - { - return t.IsGenericType && IsOptionType(t) ? t.GenericTypeArguments[0] : null; - } + public static Type? GetOptionUnderlyingType(Type t) => Instance?.GetOptionUnderlyingType(t); - public static object? GetValue(IObjectDescriptor objectDescriptor) - { - if (!IsOptionType(objectDescriptor.Type)) - { - throw new InvalidOperationException("Should not be called on non-Option<> type"); - } + public static object? GetValue(IObjectDescriptor objectDescriptor) => Instance?.GetValue(objectDescriptor); - if (objectDescriptor.Value is null) - { - return null; - } + public static bool IsFsharpListType(Type t) => Instance?.IsFsharpListType(t) ?? false; - return objectDescriptor.Type.GetProperty("Value").GetValue(objectDescriptor.Value); - } - - public static bool IsFsharpListType(Type t) - { - return t.Namespace == "Microsoft.FSharp.Collections" && t.Name == "FSharpList`1"; - } - - public static object? CreateFsharpListFromArray(Type t, Type itemsType, Array arr) - { - if (!IsFsharpListType(t)) - { - return null; - } - - var fsharpList = - t.Assembly - .GetType("Microsoft.FSharp.Collections.ListModule") - .GetMethod("OfArray") - .MakeGenericMethod(itemsType) - .Invoke(null, [arr]); - - return fsharpList; - } + public static object? CreateFsharpListFromArray(Type t, Type itemsType, Array arr) => Instance?.CreateFsharpListFromArray(t, itemsType, arr); } } diff --git a/YamlDotNet/Helpers/IFsharpHelper.cs b/YamlDotNet/Helpers/IFsharpHelper.cs new file mode 100644 index 00000000..ec4c5c94 --- /dev/null +++ b/YamlDotNet/Helpers/IFsharpHelper.cs @@ -0,0 +1,35 @@ +// This file is part of YamlDotNet - A .NET library for YAML. +// Copyright (c) Antoine Aubry and contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using YamlDotNet.Serialization; + +namespace YamlDotNet.Helpers +{ + public interface IFsharpHelper + { + bool IsOptionType(Type t); + Type? GetOptionUnderlyingType(Type t); + object? GetValue(IObjectDescriptor objectDescriptor); + bool IsFsharpListType(Type t); + object? CreateFsharpListFromArray(Type t, Type itemsType, Array arr); + } +} diff --git a/YamlDotNet/Helpers/NullFsharpHelper.cs b/YamlDotNet/Helpers/NullFsharpHelper.cs new file mode 100644 index 00000000..b2a1288f --- /dev/null +++ b/YamlDotNet/Helpers/NullFsharpHelper.cs @@ -0,0 +1,42 @@ +// This file is part of YamlDotNet - A .NET library for YAML. +// Copyright (c) Antoine Aubry and contributors +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +// of the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +using System; +using YamlDotNet.Serialization; + +namespace YamlDotNet.Helpers +{ + /// + /// Empty implementation of the fsharphelper to allow trimming of csharp applications. + /// + public class NullFsharpHelper : IFsharpHelper + { + public object? CreateFsharpListFromArray(Type t, Type itemsType, Array arr) => null; + + public Type? GetOptionUnderlyingType(Type t) => null; + + public object? GetValue(IObjectDescriptor objectDescriptor) => null; + + public bool IsFsharpListType(Type t) => false; + + public bool IsOptionType(Type t) => false; + } +} diff --git a/YamlDotNet/Serialization/DeserializerBuilder.cs b/YamlDotNet/Serialization/DeserializerBuilder.cs index 3c0f27b7..2b51b677 100755 --- a/YamlDotNet/Serialization/DeserializerBuilder.cs +++ b/YamlDotNet/Serialization/DeserializerBuilder.cs @@ -485,6 +485,11 @@ public DeserializerBuilder WithDuplicateKeyChecking() /// public IDeserializer Build() { + if (FsharpHelper.Instance == null) + { + FsharpHelper.Instance = new DefaultFsharpHelper(); + } + return Deserializer.FromValueDeserializer(BuildValueDeserializer()); } diff --git a/YamlDotNet/Serialization/SerializerBuilder.cs b/YamlDotNet/Serialization/SerializerBuilder.cs index ec9a7feb..dd6420e4 100755 --- a/YamlDotNet/Serialization/SerializerBuilder.cs +++ b/YamlDotNet/Serialization/SerializerBuilder.cs @@ -688,6 +688,11 @@ public SerializerBuilder WithIndentedSequences() /// public ISerializer Build() { + if (FsharpHelper.Instance == null) + { + FsharpHelper.Instance = new DefaultFsharpHelper(); + } + return Serializer.FromValueSerializer(BuildValueSerializer(), emitterSettings); } diff --git a/YamlDotNet/Serialization/StaticDeserializerBuilder.cs b/YamlDotNet/Serialization/StaticDeserializerBuilder.cs index 572e53c9..90dd6c09 100644 --- a/YamlDotNet/Serialization/StaticDeserializerBuilder.cs +++ b/YamlDotNet/Serialization/StaticDeserializerBuilder.cs @@ -37,6 +37,7 @@ using YamlDotNet.Serialization.TypeResolvers; using YamlDotNet.Serialization.Utilities; using YamlDotNet.Serialization.ValueDeserializers; +using YamlDotNet.Helpers; namespace YamlDotNet.Serialization {