< Summary

Information
Line coverage
0%
Covered lines: 0
Uncovered lines: 60
Coverable lines: 60
Total lines: 127
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 36
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

C:\h\w\B31A098C\w\BB5A0A33\e\runtime-utils\Runner\runtime\src\libraries\System.Text.Json\src\System\Text\Json\Serialization\Converters\Collection\IEnumerableConverterFactoryHelpers.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Diagnostics;
 5using System.Diagnostics.CodeAnalysis;
 6using System.Reflection;
 7using System.Text.Json.Reflection;
 8
 9namespace System.Text.Json.Serialization
 10{
 11    internal static class IEnumerableConverterFactoryHelpers
 12    {
 13        // System.Text.Json doesn't take a direct reference to System.Collections.Immutable so
 14        // any netstandard2.0 consumers don't need to reference System.Collections.Immutable.
 15        // So instead, implement a "weak reference" by using strings to check for Immutable types.
 16
 17        // Don't use DynamicDependency attributes to the Immutable Collection types so they can be trimmed in applicatio
 18        internal const string ImmutableConvertersUnreferencedCodeMessage = "System.Collections.Immutable converters use 
 19
 20        [RequiresUnreferencedCode(ImmutableConvertersUnreferencedCodeMessage)]
 21        [RequiresDynamicCode(ImmutableConvertersUnreferencedCodeMessage)]
 22        public static MethodInfo GetImmutableEnumerableCreateRangeMethod(this Type type, Type elementType)
 023        {
 024            Type? constructingType = GetImmutableEnumerableConstructingType(type);
 025            if (constructingType != null)
 026            {
 027                MethodInfo[] constructingTypeMethods = constructingType.GetMethods();
 028                foreach (MethodInfo method in constructingTypeMethods)
 029                {
 030                    if (method.Name == ReflectionExtensions.CreateRangeMethodName &&
 031                        method.GetParameters().Length == 1 &&
 032                        method.IsGenericMethod &&
 033                        method.GetGenericArguments().Length == 1)
 034                    {
 035                        return method.MakeGenericMethod(elementType);
 36                    }
 037                }
 038            }
 39
 040            ThrowHelper.ThrowNotSupportedException_SerializationNotSupported(type);
 41            return null!;
 042        }
 43
 44        [RequiresUnreferencedCode(ImmutableConvertersUnreferencedCodeMessage)]
 45        [RequiresDynamicCode(ImmutableConvertersUnreferencedCodeMessage)]
 46        public static MethodInfo GetImmutableDictionaryCreateRangeMethod(this Type type, Type keyType, Type valueType)
 047        {
 048            Type? constructingType = GetImmutableDictionaryConstructingType(type);
 049            if (constructingType != null)
 050            {
 051                MethodInfo[] constructingTypeMethods = constructingType.GetMethods();
 052                foreach (MethodInfo method in constructingTypeMethods)
 053                {
 054                    if (method.Name == ReflectionExtensions.CreateRangeMethodName &&
 055                        method.GetParameters().Length == 1 &&
 056                        method.IsGenericMethod &&
 057                        method.GetGenericArguments().Length == 2)
 058                    {
 059                        return method.MakeGenericMethod(keyType, valueType);
 60                    }
 061                }
 062            }
 63
 064            ThrowHelper.ThrowNotSupportedException_SerializationNotSupported(type);
 65            return null!;
 066        }
 67
 68        [RequiresUnreferencedCode(ImmutableConvertersUnreferencedCodeMessage)]
 69        [RequiresDynamicCode(ImmutableConvertersUnreferencedCodeMessage)]
 70        private static Type? GetImmutableEnumerableConstructingType(Type type)
 071        {
 072            Debug.Assert(type.IsImmutableEnumerableType());
 73
 074            string? constructingTypeName = type.GetImmutableEnumerableConstructingTypeName();
 75
 076            return constructingTypeName == null
 077                ? null
 078                : type.Assembly.GetType(constructingTypeName);
 079        }
 80
 81        [RequiresUnreferencedCode(ImmutableConvertersUnreferencedCodeMessage)]
 82        [RequiresDynamicCode(ImmutableConvertersUnreferencedCodeMessage)]
 83        private static Type? GetImmutableDictionaryConstructingType(Type type)
 084        {
 085            Debug.Assert(type.IsImmutableDictionaryType());
 86
 087            string? constructingTypeName = type.GetImmutableDictionaryConstructingTypeName();
 88
 089            return constructingTypeName == null
 090                ? null
 091                : type.Assembly.GetType(constructingTypeName);
 092        }
 93
 94        public static bool IsNonGenericStackOrQueue(this Type type)
 095        {
 96#if NET
 97            // Optimize for linking scenarios where mscorlib is trimmed out.
 98            const string stackTypeName = "System.Collections.Stack, System.Collections.NonGeneric";
 99            const string queueTypeName = "System.Collections.Queue, System.Collections.NonGeneric";
 100#else
 101            const string stackTypeName = "System.Collections.Stack, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKe
 102            const string queueTypeName = "System.Collections.Queue, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKe
 103#endif
 104
 0105            Type? stackType = GetTypeIfExists(stackTypeName);
 0106            if (stackType?.IsAssignableFrom(type) == true)
 0107            {
 0108                return true;
 109            }
 110
 0111            Type? queueType = GetTypeIfExists(queueTypeName);
 0112            if (queueType?.IsAssignableFrom(type) == true)
 0113            {
 0114                return true;
 115            }
 116
 0117            return false;
 0118        }
 119
 120        // This method takes an unannotated string which makes trimming reflection analysis lose track of the type we ar
 121        // looking for. This indirection allows the removal of the type if it is not used in the calling application.
 122        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2057:TypeGetType",
 123            Justification = "This method exists to allow for 'weak references' to the Stack and Queue types. If those ty
 124            "they will be preserved by the app and Type.GetType will return them. If those types are not used in the app
 0125        private static Type? GetTypeIfExists(string name) => Type.GetType(name, false);
 126    }
 127}