<PackageReference Include="System.Text.Json" Version="10.0.0-rc.2.25502.107" />

NullabilityInfoContext

sealed class NullabilityInfoContext
using System.Collections.Generic; using System.Collections.ObjectModel; namespace System.Reflection { internal sealed class NullabilityInfoContext { [Flags] private enum NotAnnotatedStatus { None = 0, Private = 1, Internal = 2 } private readonly struct NullableAttributeStateParser { private static readonly object UnknownByte = (byte)0; private readonly object _nullableAttributeArgument; public static NullableAttributeStateParser Unknown => new NullableAttributeStateParser(UnknownByte); public NullableAttributeStateParser(object nullableAttributeArgument) { _nullableAttributeArgument = nullableAttributeArgument; } public bool ParseNullableState(int index, ref System.Reflection.NullabilityState state) { object nullableAttributeArgument = _nullableAttributeArgument; if (nullableAttributeArgument is byte) { byte b = (byte)nullableAttributeArgument; byte b2 = b; state = TranslateByte(b2); return true; } ReadOnlyCollection<CustomAttributeTypedArgument> readOnlyCollection = nullableAttributeArgument as ReadOnlyCollection<CustomAttributeTypedArgument>; if (readOnlyCollection != null) { ReadOnlyCollection<CustomAttributeTypedArgument> readOnlyCollection2 = readOnlyCollection; if (index < readOnlyCollection2.Count) { object value = readOnlyCollection2[index].Value; if (value is byte) { byte b3 = (byte)value; state = TranslateByte(b3); return true; } } } return false; } } private const string CompilerServicesNameSpace = "System.Runtime.CompilerServices"; private readonly Dictionary<Module, NotAnnotatedStatus> _publicOnlyModules = new Dictionary<Module, NotAnnotatedStatus>(); private readonly Dictionary<MemberInfo, System.Reflection.NullabilityState> _context = new Dictionary<MemberInfo, System.Reflection.NullabilityState>(); private System.Reflection.NullabilityState? GetNullableContext(MemberInfo memberInfo) { while (memberInfo != (MemberInfo)null) { if (_context.TryGetValue(memberInfo, out System.Reflection.NullabilityState value)) return value; foreach (CustomAttributeData customAttributesDatum in memberInfo.GetCustomAttributesData()) { if (customAttributesDatum.AttributeType.Name == "NullableContextAttribute" && customAttributesDatum.AttributeType.Namespace == "System.Runtime.CompilerServices" && customAttributesDatum.ConstructorArguments.Count == 1) { value = TranslateByte(customAttributesDatum.ConstructorArguments[0].Value); _context.Add(memberInfo, value); return value; } } memberInfo = memberInfo.DeclaringType; } return null; } public System.Reflection.NullabilityInfo Create(ParameterInfo parameterInfo) { System.ExceptionPolyfills.ThrowIfNull(parameterInfo, "parameterInfo"); IList<CustomAttributeData> customAttributesData = parameterInfo.GetCustomAttributesData(); MethodBase methodBase = parameterInfo.Member as MethodBase; NullableAttributeStateParser parser = ((object)methodBase != null && IsPrivateOrInternalMethodAndAnnotationDisabled(methodBase)) ? NullableAttributeStateParser.Unknown : CreateParser(customAttributesData); System.Reflection.NullabilityInfo nullabilityInfo = GetNullabilityInfo(parameterInfo.Member, parameterInfo.ParameterType, parser); if (nullabilityInfo.ReadState != 0) CheckParameterMetadataType(parameterInfo, nullabilityInfo); CheckNullabilityAttributes(nullabilityInfo, customAttributesData); return nullabilityInfo; } private void CheckParameterMetadataType(ParameterInfo parameter, System.Reflection.NullabilityInfo nullability) { MemberInfo member = parameter.Member; ConstructorInfo constructorInfo = member as ConstructorInfo; MemberInfo metaMember; ParameterInfo parameterInfo; if ((object)constructorInfo == null) { MethodInfo methodInfo = member as MethodInfo; if ((object)methodInfo == null) return; MethodInfo methodMetadataDefinition = GetMethodMetadataDefinition(methodInfo); metaMember = methodMetadataDefinition; parameterInfo = (string.IsNullOrEmpty(parameter.Name) ? methodMetadataDefinition.ReturnParameter : GetMetaParameter(methodMetadataDefinition, parameter)); } else parameterInfo = GetMetaParameter((MethodBase)(metaMember = (ConstructorInfo)GetMemberMetadataDefinition(constructorInfo)), parameter); if (parameterInfo != null) CheckGenericParameters(nullability, metaMember, parameterInfo.ParameterType, parameter.Member.ReflectedType); } private static ParameterInfo GetMetaParameter(MethodBase metaMethod, ParameterInfo parameter) { ReadOnlySpan<ParameterInfo> parametersAsSpan = metaMethod.GetParametersAsSpan(); for (int i = 0; i < parametersAsSpan.Length; i++) { if (parameter.Position == i && parameter.Name == parametersAsSpan[i].Name) return parametersAsSpan[i]; } return null; } private static MethodInfo GetMethodMetadataDefinition(MethodInfo method) { if (method.IsGenericMethod && !method.IsGenericMethodDefinition) method = method.GetGenericMethodDefinition(); return (MethodInfo)GetMemberMetadataDefinition(method); } private static void CheckNullabilityAttributes(System.Reflection.NullabilityInfo nullability, IList<CustomAttributeData> attributes) { System.Reflection.NullabilityState nullabilityState = System.Reflection.NullabilityState.Unknown; System.Reflection.NullabilityState nullabilityState2 = System.Reflection.NullabilityState.Unknown; foreach (CustomAttributeData attribute in attributes) { if (attribute.AttributeType.Namespace == "System.Diagnostics.CodeAnalysis") { if (attribute.AttributeType.Name == "NotNullAttribute") nullabilityState = System.Reflection.NullabilityState.NotNull; else if ((attribute.AttributeType.Name == "MaybeNullAttribute" || attribute.AttributeType.Name == "MaybeNullWhenAttribute") && nullabilityState == System.Reflection.NullabilityState.Unknown && !IsValueTypeOrValueTypeByRef(nullability.Type)) { nullabilityState = System.Reflection.NullabilityState.Nullable; } else if (attribute.AttributeType.Name == "DisallowNullAttribute") { nullabilityState2 = System.Reflection.NullabilityState.NotNull; } else if (attribute.AttributeType.Name == "AllowNullAttribute" && nullabilityState2 == System.Reflection.NullabilityState.Unknown && !IsValueTypeOrValueTypeByRef(nullability.Type)) { nullabilityState2 = System.Reflection.NullabilityState.Nullable; } } } if (nullabilityState != 0) nullability.ReadState = nullabilityState; if (nullabilityState2 != 0) nullability.WriteState = nullabilityState2; } public System.Reflection.NullabilityInfo Create(PropertyInfo propertyInfo) { System.ExceptionPolyfills.ThrowIfNull(propertyInfo, "propertyInfo"); MethodInfo getMethod = propertyInfo.GetGetMethod(true); MethodInfo setMethod = propertyInfo.GetSetMethod(true); NullableAttributeStateParser parser = ((getMethod == (MethodInfo)null || IsPrivateOrInternalMethodAndAnnotationDisabled(getMethod)) && (setMethod == (MethodInfo)null || IsPrivateOrInternalMethodAndAnnotationDisabled(setMethod))) ? NullableAttributeStateParser.Unknown : CreateParser(propertyInfo.GetCustomAttributesData()); System.Reflection.NullabilityInfo nullabilityInfo = GetNullabilityInfo(propertyInfo, propertyInfo.PropertyType, parser); if (getMethod != (MethodInfo)null) CheckNullabilityAttributes(nullabilityInfo, getMethod.ReturnParameter.GetCustomAttributesData()); else nullabilityInfo.ReadState = System.Reflection.NullabilityState.Unknown; if (setMethod != (MethodInfo)null) { ReadOnlySpan<ParameterInfo> parametersAsSpan = setMethod.GetParametersAsSpan(); ParameterInfo parameterInfo = parametersAsSpan[parametersAsSpan.Length - 1]; CheckNullabilityAttributes(nullabilityInfo, parameterInfo.GetCustomAttributesData()); } else nullabilityInfo.WriteState = System.Reflection.NullabilityState.Unknown; return nullabilityInfo; } private bool IsPrivateOrInternalMethodAndAnnotationDisabled(MethodBase method) { if ((method.IsPrivate || method.IsFamilyAndAssembly || method.IsAssembly) && IsPublicOnly(method.IsPrivate, method.IsFamilyAndAssembly, method.IsAssembly, method.Module)) return true; return false; } public System.Reflection.NullabilityInfo Create(EventInfo eventInfo) { System.ExceptionPolyfills.ThrowIfNull(eventInfo, "eventInfo"); return GetNullabilityInfo(eventInfo, eventInfo.EventHandlerType, CreateParser(eventInfo.GetCustomAttributesData())); } public System.Reflection.NullabilityInfo Create(FieldInfo fieldInfo) { System.ExceptionPolyfills.ThrowIfNull(fieldInfo, "fieldInfo"); IList<CustomAttributeData> customAttributesData = fieldInfo.GetCustomAttributesData(); NullableAttributeStateParser parser = IsPrivateOrInternalFieldAndAnnotationDisabled(fieldInfo) ? NullableAttributeStateParser.Unknown : CreateParser(customAttributesData); System.Reflection.NullabilityInfo nullabilityInfo = GetNullabilityInfo(fieldInfo, fieldInfo.FieldType, parser); CheckNullabilityAttributes(nullabilityInfo, customAttributesData); return nullabilityInfo; } private bool IsPrivateOrInternalFieldAndAnnotationDisabled(FieldInfo fieldInfo) { if ((fieldInfo.IsPrivate || fieldInfo.IsFamilyAndAssembly || fieldInfo.IsAssembly) && IsPublicOnly(fieldInfo.IsPrivate, fieldInfo.IsFamilyAndAssembly, fieldInfo.IsAssembly, fieldInfo.Module)) return true; return false; } private bool IsPublicOnly(bool isPrivate, bool isFamilyAndAssembly, bool isAssembly, Module module) { if (!_publicOnlyModules.TryGetValue(module, out NotAnnotatedStatus value)) { value = PopulateAnnotationInfo(module.GetCustomAttributesData()); _publicOnlyModules.Add(module, value); } if (value == NotAnnotatedStatus.None) return false; if (((isPrivate | isFamilyAndAssembly) && value.HasFlag(NotAnnotatedStatus.Private)) || (isAssembly && value.HasFlag(NotAnnotatedStatus.Internal))) return true; return false; } private static NotAnnotatedStatus PopulateAnnotationInfo(IList<CustomAttributeData> customAttributes) { foreach (CustomAttributeData customAttribute in customAttributes) { if (customAttribute.AttributeType.Name == "NullablePublicOnlyAttribute" && customAttribute.AttributeType.Namespace == "System.Runtime.CompilerServices" && customAttribute.ConstructorArguments.Count == 1) { object value = customAttribute.ConstructorArguments[0].Value; bool flag = default(bool); int num; if (value is bool) { flag = (bool)value; num = 1; } else num = 0; if ((num & (flag ? 1 : 0)) == 0) return NotAnnotatedStatus.Private; return NotAnnotatedStatus.Private | NotAnnotatedStatus.Internal; } } return NotAnnotatedStatus.None; } private System.Reflection.NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, NullableAttributeStateParser parser) { int index = 0; System.Reflection.NullabilityInfo nullabilityInfo = GetNullabilityInfo(memberInfo, type, parser, ref index); if (nullabilityInfo.ReadState != 0) TryLoadGenericMetaTypeNullability(memberInfo, nullabilityInfo); return nullabilityInfo; } private System.Reflection.NullabilityInfo GetNullabilityInfo(MemberInfo memberInfo, Type type, NullableAttributeStateParser parser, ref int index) { System.Reflection.NullabilityState state = System.Reflection.NullabilityState.Unknown; System.Reflection.NullabilityInfo elementType = null; System.Reflection.NullabilityInfo[] array = Array.Empty<System.Reflection.NullabilityInfo>(); Type type2 = type; if (type2.IsByRef || type2.IsPointer) type2 = type2.GetElementType(); if (type2.IsValueType) { Type underlyingType = Nullable.GetUnderlyingType(type2); if ((object)underlyingType != null) { type2 = underlyingType; state = System.Reflection.NullabilityState.Nullable; } else state = System.Reflection.NullabilityState.NotNull; if (type2.IsGenericType) index++; } else { if (!parser.ParseNullableState(index++, ref state)) { System.Reflection.NullabilityState? nullableContext = GetNullableContext(memberInfo); if (nullableContext.HasValue) { System.Reflection.NullabilityState valueOrDefault = nullableContext.GetValueOrDefault(); state = valueOrDefault; } } if (type2.IsArray) elementType = GetNullabilityInfo(memberInfo, type2.GetElementType(), parser, ref index); } if (type2.IsGenericType) { Type[] genericArguments = type2.GetGenericArguments(); array = new System.Reflection.NullabilityInfo[genericArguments.Length]; for (int i = 0; i < genericArguments.Length; i++) { array[i] = GetNullabilityInfo(memberInfo, genericArguments[i], parser, ref index); } } return new System.Reflection.NullabilityInfo(type, state, state, elementType, array); } private static NullableAttributeStateParser CreateParser(IList<CustomAttributeData> customAttributes) { foreach (CustomAttributeData customAttribute in customAttributes) { if (customAttribute.AttributeType.Name == "NullableAttribute" && customAttribute.AttributeType.Namespace == "System.Runtime.CompilerServices" && customAttribute.ConstructorArguments.Count == 1) return new NullableAttributeStateParser(customAttribute.ConstructorArguments[0].Value); } return new NullableAttributeStateParser(null); } private void TryLoadGenericMetaTypeNullability(MemberInfo memberInfo, System.Reflection.NullabilityInfo nullability) { MemberInfo memberMetadataDefinition = GetMemberMetadataDefinition(memberInfo); Type type = null; FieldInfo fieldInfo = memberMetadataDefinition as FieldInfo; if ((object)fieldInfo != null) type = fieldInfo.FieldType; else { PropertyInfo propertyInfo = memberMetadataDefinition as PropertyInfo; if ((object)propertyInfo != null) type = GetPropertyMetaType(propertyInfo); } if (type != (Type)null) CheckGenericParameters(nullability, memberMetadataDefinition, type, memberInfo.ReflectedType); } private static MemberInfo GetMemberMetadataDefinition(MemberInfo member) { Type declaringType = member.DeclaringType; if (declaringType != (Type)null && declaringType.IsGenericType && !declaringType.IsGenericTypeDefinition) return NetstandardHelpers.GetMemberWithSameMetadataDefinitionAs(declaringType.GetGenericTypeDefinition(), member); return member; } private static Type GetPropertyMetaType(PropertyInfo property) { MethodInfo getMethod = property.GetGetMethod(true); if ((object)getMethod != null) return getMethod.ReturnType; return property.GetSetMethod(true).GetParametersAsSpan()[0].ParameterType; } private void CheckGenericParameters(System.Reflection.NullabilityInfo nullability, MemberInfo metaMember, Type metaType, Type reflectedType) { if (metaType.IsGenericParameter) { if (nullability.ReadState == System.Reflection.NullabilityState.NotNull) TryUpdateGenericParameterNullability(nullability, metaType, reflectedType); } else if (metaType.ContainsGenericParameters) { if (nullability.GenericTypeArguments.Length != 0) { Type[] genericArguments = metaType.GetGenericArguments(); for (int i = 0; i < genericArguments.Length; i++) { CheckGenericParameters(nullability.GenericTypeArguments[i], metaMember, genericArguments[i], reflectedType); } } else { System.Reflection.NullabilityInfo elementType = nullability.ElementType; if (elementType != null && metaType.IsArray) CheckGenericParameters(elementType, metaMember, metaType.GetElementType(), reflectedType); else if (metaType.IsByRef) { CheckGenericParameters(nullability, metaMember, metaType.GetElementType(), reflectedType); } } } } private bool TryUpdateGenericParameterNullability(System.Reflection.NullabilityInfo nullability, Type genericParameter, Type reflectedType) { if ((object)reflectedType != null && !genericParameter.IsGenericMethodParameter() && TryUpdateGenericTypeParameterNullabilityFromReflectedType(nullability, genericParameter, reflectedType, reflectedType)) return true; if (IsValueTypeOrValueTypeByRef(nullability.Type)) return true; System.Reflection.NullabilityState state = System.Reflection.NullabilityState.Unknown; if (CreateParser(genericParameter.GetCustomAttributesData()).ParseNullableState(0, ref state)) { nullability.ReadState = state; nullability.WriteState = state; return true; } System.Reflection.NullabilityState? nullableContext = GetNullableContext(genericParameter); if (nullableContext.HasValue) { System.Reflection.NullabilityState nullabilityState2 = nullability.WriteState = (nullability.ReadState = nullableContext.GetValueOrDefault()); return true; } return false; } private bool TryUpdateGenericTypeParameterNullabilityFromReflectedType(System.Reflection.NullabilityInfo nullability, Type genericParameter, Type context, Type reflectedType) { Type type = (context.IsGenericType && !context.IsGenericTypeDefinition) ? context.GetGenericTypeDefinition() : context; if (genericParameter.DeclaringType == type) return false; Type baseType = type.BaseType; if ((object)baseType == null) return false; if (!baseType.IsGenericType || (baseType.IsGenericTypeDefinition ? baseType : baseType.GetGenericTypeDefinition()) != genericParameter.DeclaringType) return TryUpdateGenericTypeParameterNullabilityFromReflectedType(nullability, genericParameter, baseType, reflectedType); Type[] genericArguments = baseType.GetGenericArguments(); Type type2 = genericArguments[genericParameter.GenericParameterPosition]; if (type2.IsGenericParameter) return TryUpdateGenericParameterNullability(nullability, type2, reflectedType); NullableAttributeStateParser parser = CreateParser(type.GetCustomAttributesData()); int index = 1; for (int i = 0; i < genericParameter.GenericParameterPosition; i++) { index += <TryUpdateGenericTypeParameterNullabilityFromReflectedType>g__CountNullabilityStates|25_0(genericArguments[i]); } return TryPopulateNullabilityInfo(nullability, parser, ref index); } private static bool TryPopulateNullabilityInfo(System.Reflection.NullabilityInfo nullability, NullableAttributeStateParser parser, ref int index) { bool flag = IsValueTypeOrValueTypeByRef(nullability.Type); if (!flag) { System.Reflection.NullabilityState state = System.Reflection.NullabilityState.Unknown; if (!parser.ParseNullableState(index, ref state)) return false; nullability.ReadState = state; nullability.WriteState = state; } if (!flag || (Nullable.GetUnderlyingType(nullability.Type) ?? nullability.Type).IsGenericType) index++; if (nullability.GenericTypeArguments.Length != 0) { System.Reflection.NullabilityInfo[] genericTypeArguments = nullability.GenericTypeArguments; for (int i = 0; i < genericTypeArguments.Length; i++) { TryPopulateNullabilityInfo(genericTypeArguments[i], parser, ref index); } } else { System.Reflection.NullabilityInfo elementType = nullability.ElementType; if (elementType != null) TryPopulateNullabilityInfo(elementType, parser, ref index); } return true; } private static System.Reflection.NullabilityState TranslateByte(object value) { if (!(value is byte)) return System.Reflection.NullabilityState.Unknown; byte b = (byte)value; return TranslateByte(b); } private static System.Reflection.NullabilityState TranslateByte(byte b) { switch (b) { case 1: return System.Reflection.NullabilityState.NotNull; case 2: return System.Reflection.NullabilityState.Nullable; default: return System.Reflection.NullabilityState.Unknown; } } private static bool IsValueTypeOrValueTypeByRef(Type type) { if (!type.IsValueType) { if (type.IsByRef || type.IsPointer) return type.GetElementType().IsValueType; return false; } return true; } } }