< Summary

Line coverage
59%
Covered lines: 119
Uncovered lines: 82
Coverable lines: 201
Total lines: 515
Line coverage: 59.2%
Branch coverage
28%
Covered branches: 57
Total branches: 202
Branch coverage: 28.2%
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\Common\ReflectionExtensions.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.Reflection;
 6using System.Collections.Generic;
 7#if !BUILDING_SOURCE_GENERATOR
 8using System.Diagnostics.CodeAnalysis;
 9#endif
 10
 11namespace System.Text.Json.Reflection
 12{
 13    internal static partial class ReflectionExtensions
 14    {
 15        // Immutable collection types.
 16        private const string ImmutableArrayGenericTypeName = "System.Collections.Immutable.ImmutableArray`1";
 17        private const string ImmutableListGenericTypeName = "System.Collections.Immutable.ImmutableList`1";
 18        private const string ImmutableListGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableList`1";
 19        private const string ImmutableStackGenericTypeName = "System.Collections.Immutable.ImmutableStack`1";
 20        private const string ImmutableStackGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableStack`1";
 21        private const string ImmutableQueueGenericTypeName = "System.Collections.Immutable.ImmutableQueue`1";
 22        private const string ImmutableQueueGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableQueue`1";
 23        private const string ImmutableSortedSetGenericTypeName = "System.Collections.Immutable.ImmutableSortedSet`1";
 24        private const string ImmutableHashSetGenericTypeName = "System.Collections.Immutable.ImmutableHashSet`1";
 25        private const string ImmutableSetGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableSet`1";
 26        private const string ImmutableDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableDictionary`2";
 27        private const string ImmutableDictionaryGenericInterfaceTypeName = "System.Collections.Immutable.IImmutableDicti
 28        private const string ImmutableSortedDictionaryGenericTypeName = "System.Collections.Immutable.ImmutableSortedDic
 29
 30        // Immutable collection builder types.
 31        private const string ImmutableArrayTypeName = "System.Collections.Immutable.ImmutableArray";
 32        private const string ImmutableListTypeName = "System.Collections.Immutable.ImmutableList";
 33        private const string ImmutableStackTypeName = "System.Collections.Immutable.ImmutableStack";
 34        private const string ImmutableQueueTypeName = "System.Collections.Immutable.ImmutableQueue";
 35        private const string ImmutableSortedSetTypeName = "System.Collections.Immutable.ImmutableSortedSet";
 36        private const string ImmutableHashSetTypeName = "System.Collections.Immutable.ImmutableHashSet";
 37        private const string ImmutableDictionaryTypeName = "System.Collections.Immutable.ImmutableDictionary";
 38        private const string ImmutableSortedDictionaryTypeName = "System.Collections.Immutable.ImmutableSortedDictionary
 39
 40        public const string CreateRangeMethodName = "CreateRange";
 41
 42        public static Type? GetCompatibleGenericBaseClass(this Type type, Type? baseType)
 136643        {
 136644            if (baseType is null)
 045            {
 046                return null;
 47            }
 48
 136649            Debug.Assert(baseType.IsGenericType);
 136650            Debug.Assert(!baseType.IsInterface);
 136651            Debug.Assert(baseType == baseType.GetGenericTypeDefinition());
 52
 136653            Type? baseTypeToCheck = type;
 54
 173055            while (baseTypeToCheck != null && baseTypeToCheck != typeof(object))
 136656            {
 136657                if (baseTypeToCheck.IsGenericType)
 136658                {
 136659                    Type genericTypeToCheck = baseTypeToCheck.GetGenericTypeDefinition();
 136660                    if (genericTypeToCheck == baseType)
 100261                    {
 100262                        return baseTypeToCheck;
 63                    }
 36464                }
 65
 36466                baseTypeToCheck = baseTypeToCheck.BaseType;
 36467            }
 68
 36469            return null;
 136670        }
 71
 72#if !BUILDING_SOURCE_GENERATOR
 73        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern",
 74            Justification = "The 'interfaceType' must exist and so trimmer kept it. In which case " +
 75                "It also kept it on any type which implements it. The below call to GetInterfaces " +
 76                "may return fewer results when trimmed but it will return the 'interfaceType' " +
 77                "if the type implemented it, even after trimming.")]
 78#endif
 79        public static Type? GetCompatibleGenericInterface(this Type type, Type? interfaceType)
 230180        {
 230181            if (interfaceType is null)
 082            {
 083                return null;
 84            }
 85
 230186            Debug.Assert(interfaceType.IsGenericType);
 230187            Debug.Assert(interfaceType.IsInterface);
 230188            Debug.Assert(interfaceType == interfaceType.GetGenericTypeDefinition());
 89
 230190            Type interfaceToCheck = type;
 91
 230192            if (interfaceToCheck.IsGenericType)
 230193            {
 230194                interfaceToCheck = interfaceToCheck.GetGenericTypeDefinition();
 230195            }
 96
 230197            if (interfaceToCheck == interfaceType)
 098            {
 099                return type;
 100            }
 101
 25889102            foreach (Type typeToCheck in type.GetInterfaces())
 9493103            {
 9493104                if (typeToCheck.IsGenericType)
 5759105                {
 5759106                    Type genericInterfaceToCheck = typeToCheck.GetGenericTypeDefinition();
 5759107                    if (genericInterfaceToCheck == interfaceType)
 0108                    {
 0109                        return typeToCheck;
 110                    }
 5759111                }
 9493112            }
 113
 2301114            return null;
 2301115        }
 116
 117        public static bool IsImmutableDictionaryType(this Type type)
 0118        {
 0119            if (!type.IsGenericType || !type.Assembly.FullName!.StartsWith("System.Collections.Immutable", StringCompari
 0120            {
 0121                return false;
 122            }
 123
 0124            switch (GetBaseNameFromGenericType(type))
 125            {
 126                case ImmutableDictionaryGenericTypeName:
 127                case ImmutableDictionaryGenericInterfaceTypeName:
 128                case ImmutableSortedDictionaryGenericTypeName:
 0129                    return true;
 130                default:
 0131                    return false;
 132            }
 0133        }
 134
 135        public static bool IsImmutableEnumerableType(this Type type)
 0136        {
 0137            if (!type.IsGenericType || !type.Assembly.FullName!.StartsWith("System.Collections.Immutable", StringCompari
 0138            {
 0139                return false;
 140            }
 141
 0142            switch (GetBaseNameFromGenericType(type))
 143            {
 144                case ImmutableArrayGenericTypeName:
 145                case ImmutableListGenericTypeName:
 146                case ImmutableListGenericInterfaceTypeName:
 147                case ImmutableStackGenericTypeName:
 148                case ImmutableStackGenericInterfaceTypeName:
 149                case ImmutableQueueGenericTypeName:
 150                case ImmutableQueueGenericInterfaceTypeName:
 151                case ImmutableSortedSetGenericTypeName:
 152                case ImmutableHashSetGenericTypeName:
 153                case ImmutableSetGenericInterfaceTypeName:
 0154                    return true;
 155                default:
 0156                    return false;
 157            }
 0158        }
 159
 160        public static string? GetImmutableDictionaryConstructingTypeName(this Type type)
 0161        {
 0162            Debug.Assert(type.IsImmutableDictionaryType());
 163
 164            // Use the generic type definition of the immutable collection to determine
 165            // an appropriate constructing type, i.e. a type that we can invoke the
 166            // `CreateRange<T>` method on, which returns the desired immutable collection.
 0167            switch (GetBaseNameFromGenericType(type))
 168            {
 169                case ImmutableDictionaryGenericTypeName:
 170                case ImmutableDictionaryGenericInterfaceTypeName:
 0171                    return ImmutableDictionaryTypeName;
 172                case ImmutableSortedDictionaryGenericTypeName:
 0173                    return ImmutableSortedDictionaryTypeName;
 174                default:
 175                    // We verified that the type is an immutable collection, so the
 176                    // generic definition is one of the above.
 0177                    return null;
 178            }
 0179        }
 180
 181        public static string? GetImmutableEnumerableConstructingTypeName(this Type type)
 0182        {
 0183            Debug.Assert(type.IsImmutableEnumerableType());
 184
 185            // Use the generic type definition of the immutable collection to determine
 186            // an appropriate constructing type, i.e. a type that we can invoke the
 187            // `CreateRange<T>` method on, which returns the desired immutable collection.
 0188            switch (GetBaseNameFromGenericType(type))
 189            {
 190                case ImmutableArrayGenericTypeName:
 0191                    return ImmutableArrayTypeName;
 192                case ImmutableListGenericTypeName:
 193                case ImmutableListGenericInterfaceTypeName:
 0194                    return ImmutableListTypeName;
 195                case ImmutableStackGenericTypeName:
 196                case ImmutableStackGenericInterfaceTypeName:
 0197                    return ImmutableStackTypeName;
 198                case ImmutableQueueGenericTypeName:
 199                case ImmutableQueueGenericInterfaceTypeName:
 0200                    return ImmutableQueueTypeName;
 201                case ImmutableSortedSetGenericTypeName:
 0202                    return ImmutableSortedSetTypeName;
 203                case ImmutableHashSetGenericTypeName:
 204                case ImmutableSetGenericInterfaceTypeName:
 0205                    return ImmutableHashSetTypeName;
 206                default:
 207                    // We verified that the type is an immutable collection, so the
 208                    // generic definition is one of the above.
 0209                    return null;
 210            }
 0211        }
 212
 213        private static string GetBaseNameFromGenericType(Type genericType)
 0214        {
 0215            Type genericTypeDef = genericType.GetGenericTypeDefinition();
 0216            return genericTypeDef.FullName!;
 0217        }
 218
 219        public static bool IsVirtual(this PropertyInfo propertyInfo)
 16337220        {
 16337221            return propertyInfo.GetMethod?.IsVirtual == true || propertyInfo.SetMethod?.IsVirtual == true;
 16337222        }
 223
 224        public static bool IsKeyValuePair(this Type type)
 1299225            => type.IsGenericType && type.GetGenericTypeDefinition() == typeof(KeyValuePair<,>);
 226
 227        public static bool TryGetDeserializationConstructor(
 228            [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTyp
 229            this Type type,
 230            bool useDefaultCtorInAnnotatedStructs,
 231            out ConstructorInfo? deserializationCtor)
 1299232        {
 1299233            ConstructorInfo? ctorWithAttribute = null;
 1299234            ConstructorInfo? publicParameterlessCtor = null;
 1299235            ConstructorInfo? lonePublicCtor = null;
 236
 1299237            ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.Public | BindingFlags.Instance);
 238
 1299239            if (constructors.Length == 1)
 1299240            {
 1299241                lonePublicCtor = constructors[0];
 1299242            }
 243
 6495244            foreach (ConstructorInfo constructor in constructors)
 1299245            {
 1299246                if (HasJsonConstructorAttribute(constructor))
 0247                {
 0248                    if (ctorWithAttribute != null)
 0249                    {
 0250                        deserializationCtor = null;
 0251                        return false;
 252                    }
 253
 0254                    ctorWithAttribute = constructor;
 0255                }
 1299256                else if (constructor.GetParameters().Length == 0)
 550257                {
 550258                    publicParameterlessCtor = constructor;
 550259                }
 1299260            }
 261
 262            // Search for non-public ctors with [JsonConstructor].
 5395263            foreach (ConstructorInfo constructor in type.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)
 749264            {
 749265                if (HasJsonConstructorAttribute(constructor))
 0266                {
 0267                    if (ctorWithAttribute != null)
 0268                    {
 0269                        deserializationCtor = null;
 0270                        return false;
 271                    }
 272
 0273                    ctorWithAttribute = constructor;
 0274                }
 749275            }
 276
 277            // Structs will use default constructor if attribute isn't used.
 1299278            if (useDefaultCtorInAnnotatedStructs && type.IsValueType && ctorWithAttribute == null)
 0279            {
 0280                deserializationCtor = null;
 0281                return true;
 282            }
 283
 1299284            deserializationCtor = ctorWithAttribute ?? publicParameterlessCtor ?? lonePublicCtor;
 1299285            return true;
 1299286        }
 287
 288        public static object? GetDefaultValue(this ParameterInfo parameterInfo)
 4494289        {
 4494290            Type parameterType = parameterInfo.ParameterType;
 4494291            object? defaultValue = parameterInfo.DefaultValue;
 292
 4494293            if (defaultValue is null)
 0294            {
 0295                return null;
 296            }
 297
 298            // DBNull.Value is sometimes used as the default value (returned by reflection) of nullable params in place 
 4494299            if (defaultValue == DBNull.Value && parameterType != typeof(DBNull))
 4494300            {
 4494301                return null;
 302            }
 303
 304            // Default values of enums or nullable enums are represented using the underlying type and need to be cast e
 305            // cf. https://github.com/dotnet/runtime/issues/68647
 0306            if (parameterType.IsEnum)
 0307            {
 0308                return Enum.ToObject(parameterType, defaultValue);
 309            }
 310
 0311            if (Nullable.GetUnderlyingType(parameterType) is Type underlyingType && underlyingType.IsEnum)
 0312            {
 0313                return Enum.ToObject(underlyingType, defaultValue);
 314            }
 315
 0316            return defaultValue;
 4494317        }
 318
 319        /// <summary>
 320        /// Returns the type hierarchy for the given type, starting from the current type up to the base type(s) in the 
 321        /// Interface hierarchies with multiple inheritance will return results using topological sorting.
 322        /// </summary>
 323        [RequiresUnreferencedCode("Should only be used by the reflection-based serializer.")]
 324        public static Type[] GetSortedTypeHierarchy(this Type type)
 1299325        {
 1299326            if (!type.IsInterface)
 1299327            {
 328                // Non-interface hierarchies are linear, just walk up to the earliest ancestor.
 329
 1299330                var results = new List<Type>();
 7794331                for (Type? current = type; current != null; current = current.BaseType)
 2598332                {
 2598333                    results.Add(current);
 2598334                }
 335
 1299336                return results.ToArray();
 337            }
 338            else
 0339            {
 340                // Interface hierarchies support multiple inheritance.
 341                // For consistency with class hierarchy resolution order,
 342                // sort topologically from most derived to least derived.
 0343                return JsonHelpers.TraverseGraphWithTopologicalSort(type, static t => t.GetInterfaces());
 344            }
 1299345        }
 346    }
 347}

C:\h\w\B31A098C\w\BB5A0A33\e\runtime-utils\Runner\runtime\src\libraries\System.Text.Json\src\System\ReflectionExtensions.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.Runtime.CompilerServices;
 8using System.Runtime.ExceptionServices;
 9using System.Text.Json.Serialization;
 10
 11namespace System.Text.Json.Reflection
 12{
 13    internal static partial class ReflectionExtensions
 14    {
 115        private static readonly Type s_nullableType = typeof(Nullable<>);
 16
 17        /// <summary>
 18        /// Returns <see langword="true" /> when the given type is of type <see cref="Nullable{T}"/>.
 19        /// </summary>
 20        [MethodImpl(MethodImplOptions.AggressiveInlining)]
 21        public static bool IsNullableOfT(this Type type) =>
 3333522            type.IsGenericType && type.GetGenericTypeDefinition() == s_nullableType;
 23
 449424        public static bool IsNullableType(this Type type) => !type.IsValueType || IsNullableOfT(type);
 25
 26        /// <summary>
 27        /// Returns <see langword="true" /> when the given type is assignable from <paramref name="from"/> including sup
 28        /// when <paramref name="from"/> is <see cref="Nullable{T}"/> by using the {T} generic parameter for <paramref n
 29        /// </summary>
 30        public static bool IsAssignableFromInternal(this Type type, Type from)
 1225431        {
 1225432            if (IsNullableOfT(from) && type.IsInterface)
 033            {
 034                return type.IsAssignableFrom(from.GetGenericArguments()[0]);
 35            }
 36
 1225437            return type.IsAssignableFrom(from);
 1225438        }
 39
 40        /// <summary>
 41        /// Returns <see langword="true" /> when either type is assignable to the other.
 42        /// </summary>
 43        public static bool IsInSubtypeRelationshipWith(this Type type, Type other) =>
 1225444            type.IsAssignableFromInternal(other) || other.IsAssignableFromInternal(type);
 45
 46        private static bool HasJsonConstructorAttribute(ConstructorInfo constructorInfo)
 204847            => constructorInfo.GetCustomAttribute<JsonConstructorAttribute>() != null;
 48
 49        public static bool HasRequiredMemberAttribute(this MemberInfo memberInfo)
 129950        {
 51            // For compiler related attributes we should only look at full type name rather than trying to do something 
 52            // I.e. library is targeting netstandard2.0 with polyfilled attributes and is being consumed by an app targe
 129953            return memberInfo.HasCustomAttributeWithName("System.Runtime.CompilerServices.RequiredMemberAttribute", inhe
 129954        }
 55
 56        public static bool HasSetsRequiredMembersAttribute(this MemberInfo memberInfo)
 129957        {
 58            // See comment for HasRequiredMemberAttribute for why we need to always only look at full name
 129959            return memberInfo.HasCustomAttributeWithName("System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute",
 129960        }
 61
 62        private static bool HasCustomAttributeWithName(this MemberInfo memberInfo, string fullName, bool inherit)
 259863        {
 779464            foreach (object attribute in memberInfo.GetCustomAttributes(inherit))
 065            {
 066                if (attribute.GetType().FullName == fullName)
 067                {
 068                    return true;
 69                }
 070            }
 71
 259872            return false;
 259873        }
 74
 75        public static TAttribute? GetUniqueCustomAttribute<TAttribute>(this MemberInfo memberInfo, bool inherit)
 76            where TAttribute : Attribute
 5681077        {
 5681078            object[] attributes = memberInfo.GetCustomAttributes(typeof(TAttribute), inherit);
 79
 5681080            if (attributes.Length == 0)
 5654181            {
 5654182                return null;
 83            }
 84
 26985            if (attributes.Length == 1)
 26986            {
 26987                return (TAttribute)attributes[0];
 88            }
 89
 090            ThrowHelper.ThrowInvalidOperationException_SerializationDuplicateAttribute(typeof(TAttribute), memberInfo);
 91            return null;
 5681092        }
 93
 94        /// <summary>
 95        /// Polyfill for BindingFlags.DoNotWrapExceptions
 96        /// </summary>
 97        public static object? CreateInstanceNoWrapExceptions(
 98            [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTyp
 99            Type[] parameterTypes,
 100            object?[] parameters)
 1895101        {
 1895102            ConstructorInfo ctorInfo = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.I
 103#if NET
 1895104            return ctorInfo.Invoke(BindingFlags.DoNotWrapExceptions, null, parameters, null);
 105#else
 106            object? result = null;
 107            try
 108            {
 109                result = ctorInfo.Invoke(parameters);
 110            }
 111            catch (TargetInvocationException ex)
 112            {
 113                ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
 114            }
 115
 116            return result;
 117#endif
 1895118        }
 119
 120        public static ParameterInfo GetGenericParameterDefinition(this ParameterInfo parameter)
 121        {
 122            if (parameter.Member is { DeclaringType.IsConstructedGenericType: true }
 123                                 or MethodInfo { IsGenericMethod: true, IsGenericMethodDefinition: false })
 124            {
 125                var genericMethod = (MethodBase)parameter.Member.GetGenericMemberDefinition()!;
 126                return genericMethod.GetParameters()[parameter.Position];
 127            }
 128
 129            return parameter;
 130        }
 131
 132        [UnconditionalSuppressMessage("Trimming", "IL2075:'this' argument does not satisfy 'DynamicallyAccessedMembersAt
 133            Justification = "Looking up the generic member definition of the provided member.")]
 134        public static MemberInfo GetGenericMemberDefinition(this MemberInfo member)
 135        {
 136            if (member is Type type)
 137            {
 138                return type.IsConstructedGenericType ? type.GetGenericTypeDefinition() : type;
 139            }
 140
 141            if (member.DeclaringType!.IsConstructedGenericType)
 142            {
 143                const BindingFlags AllMemberFlags =
 144                    BindingFlags.Static | BindingFlags.Instance |
 145                    BindingFlags.Public | BindingFlags.NonPublic;
 146
 147                Type genericTypeDef = member.DeclaringType.GetGenericTypeDefinition();
 148                foreach (MemberInfo genericMember in genericTypeDef.GetMember(member.Name, AllMemberFlags))
 149                {
 150                    if (genericMember.MetadataToken == member.MetadataToken)
 151                    {
 152                        return genericMember;
 153                    }
 154                }
 155
 156                Debug.Fail("Unreachable code");
 157                throw new Exception();
 158            }
 159
 160            if (member is MethodInfo { IsGenericMethod: true, IsGenericMethodDefinition: false } method)
 161            {
 162                return method.GetGenericMethodDefinition();
 163            }
 164
 165            return member;
 166        }
 167    }
 168}