mirror of https://github.com/icsharpcode/ILSpy.git
				
				
			
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							751 lines
						
					
					
						
							26 KiB
						
					
					
				
			
		
		
	
	
							751 lines
						
					
					
						
							26 KiB
						
					
					
				using System; | 
						|
using System.Collections.Immutable; | 
						|
using System.Reflection; | 
						|
using System.Reflection.Metadata; | 
						|
using System.Reflection.Metadata.Ecma335; | 
						|
using System.Reflection.PortableExecutable; | 
						|
 | 
						|
using ICSharpCode.Decompiler.TypeSystem; | 
						|
using ICSharpCode.Decompiler.Util; | 
						|
 | 
						|
using SRM = System.Reflection.Metadata; | 
						|
 | 
						|
namespace ICSharpCode.Decompiler | 
						|
{ | 
						|
	public static partial class SRMExtensions | 
						|
	{ | 
						|
		public static bool HasFlag(this TypeDefinition typeDefinition, TypeAttributes attribute) | 
						|
			=> (typeDefinition.Attributes & attribute) == attribute; | 
						|
		public static bool HasFlag(this MethodDefinition methodDefinition, MethodAttributes attribute) | 
						|
			=> (methodDefinition.Attributes & attribute) == attribute; | 
						|
		public static bool HasFlag(this FieldDefinition fieldDefinition, FieldAttributes attribute) | 
						|
			=> (fieldDefinition.Attributes & attribute) == attribute; | 
						|
		public static bool HasFlag(this PropertyDefinition propertyDefinition, PropertyAttributes attribute) | 
						|
			=> (propertyDefinition.Attributes & attribute) == attribute; | 
						|
		public static bool HasFlag(this EventDefinition eventDefinition, EventAttributes attribute) | 
						|
			=> (eventDefinition.Attributes & attribute) == attribute; | 
						|
 | 
						|
		public static bool IsTypeKind(this HandleKind kind) => | 
						|
			kind == HandleKind.TypeDefinition || kind == HandleKind.TypeReference | 
						|
			|| kind == HandleKind.TypeSpecification; | 
						|
		public static bool IsMemberKind(this HandleKind kind) => | 
						|
			kind == HandleKind.MethodDefinition || kind == HandleKind.PropertyDefinition | 
						|
			|| kind == HandleKind.FieldDefinition || kind == HandleKind.EventDefinition | 
						|
			|| kind == HandleKind.MemberReference || kind == HandleKind.MethodSpecification; | 
						|
		public static bool IsEntityHandle(this Handle handle) => | 
						|
			handle.IsNil || (byte)handle.Kind < 112; | 
						|
 | 
						|
		public static bool IsValueType(this TypeDefinitionHandle handle, MetadataReader reader) | 
						|
		{ | 
						|
			return reader.GetTypeDefinition(handle).IsValueType(reader); | 
						|
		} | 
						|
 | 
						|
		public static bool IsValueType(this TypeDefinition typeDefinition, MetadataReader reader) | 
						|
		{ | 
						|
			EntityHandle baseType = typeDefinition.GetBaseTypeOrNil(); | 
						|
			if (baseType.IsNil) | 
						|
				return false; | 
						|
			if (baseType.IsKnownType(reader, KnownTypeCode.Enum)) | 
						|
				return true; | 
						|
			if (!baseType.IsKnownType(reader, KnownTypeCode.ValueType)) | 
						|
				return false; | 
						|
			var thisType = typeDefinition.GetFullTypeName(reader); | 
						|
			return !thisType.IsKnownType(KnownTypeCode.Enum); | 
						|
		} | 
						|
 | 
						|
		public static bool IsEnum(this TypeDefinitionHandle handle, MetadataReader reader) | 
						|
		{ | 
						|
			return reader.GetTypeDefinition(handle).IsEnum(reader); | 
						|
		} | 
						|
 | 
						|
		public static bool IsEnum(this TypeDefinition typeDefinition, MetadataReader reader) | 
						|
		{ | 
						|
			EntityHandle baseType = typeDefinition.GetBaseTypeOrNil(); | 
						|
			if (baseType.IsNil) | 
						|
				return false; | 
						|
			return baseType.IsKnownType(reader, KnownTypeCode.Enum); | 
						|
		} | 
						|
 | 
						|
		public static bool IsEnum(this TypeDefinitionHandle handle, MetadataReader reader, | 
						|
			out PrimitiveTypeCode underlyingType) | 
						|
		{ | 
						|
			return reader.GetTypeDefinition(handle).IsEnum(reader, out underlyingType); | 
						|
		} | 
						|
 | 
						|
		public static bool IsEnum(this TypeDefinition typeDefinition, MetadataReader reader, | 
						|
			out PrimitiveTypeCode underlyingType) | 
						|
		{ | 
						|
			underlyingType = 0; | 
						|
			EntityHandle baseType = typeDefinition.GetBaseTypeOrNil(); | 
						|
			if (baseType.IsNil) | 
						|
				return false; | 
						|
			if (!baseType.IsKnownType(reader, KnownTypeCode.Enum)) | 
						|
				return false; | 
						|
			foreach (var handle in typeDefinition.GetFields()) | 
						|
			{ | 
						|
				var field = reader.GetFieldDefinition(handle); | 
						|
				if ((field.Attributes & FieldAttributes.Static) != 0) | 
						|
					continue; | 
						|
				var blob = reader.GetBlobReader(field.Signature); | 
						|
				if (blob.ReadSignatureHeader().Kind != SignatureKind.Field) | 
						|
					return false; | 
						|
				underlyingType = (PrimitiveTypeCode)blob.ReadByte(); | 
						|
				return true; | 
						|
			} | 
						|
			return false; | 
						|
		} | 
						|
 | 
						|
		public static bool IsDelegate(this TypeDefinitionHandle handle, MetadataReader reader) | 
						|
		{ | 
						|
			return reader.GetTypeDefinition(handle).IsDelegate(reader); | 
						|
		} | 
						|
 | 
						|
		public static bool IsDelegate(this TypeDefinition typeDefinition, MetadataReader reader) | 
						|
		{ | 
						|
			var baseType = typeDefinition.GetBaseTypeOrNil(); | 
						|
			return !baseType.IsNil && baseType.IsKnownType(reader, KnownTypeCode.MulticastDelegate); | 
						|
		} | 
						|
 | 
						|
		public static bool HasBody(this MethodDefinition methodDefinition) | 
						|
		{ | 
						|
			const MethodAttributes noBodyAttrs = MethodAttributes.Abstract | MethodAttributes.PinvokeImpl; | 
						|
			const MethodImplAttributes noBodyImplAttrs = MethodImplAttributes.InternalCall | 
						|
				| MethodImplAttributes.Native | MethodImplAttributes.Unmanaged | MethodImplAttributes.Runtime; | 
						|
			return (methodDefinition.Attributes & noBodyAttrs) == 0 && | 
						|
				(methodDefinition.ImplAttributes & noBodyImplAttrs) == 0 && | 
						|
				methodDefinition.RelativeVirtualAddress > 0; | 
						|
		} | 
						|
 | 
						|
		public static int GetCodeSize(this MethodBodyBlock body) | 
						|
		{ | 
						|
			if (body == null) | 
						|
				throw new ArgumentNullException(nameof(body)); | 
						|
 | 
						|
			return body.GetILReader().Length; | 
						|
		} | 
						|
 | 
						|
		public static MethodDefinitionHandle GetAny(this PropertyAccessors accessors) | 
						|
		{ | 
						|
			if (!accessors.Getter.IsNil) | 
						|
				return accessors.Getter; | 
						|
			return accessors.Setter; | 
						|
		} | 
						|
 | 
						|
		public static MethodDefinitionHandle GetAny(this EventAccessors accessors) | 
						|
		{ | 
						|
			if (!accessors.Adder.IsNil) | 
						|
				return accessors.Adder; | 
						|
			if (!accessors.Remover.IsNil) | 
						|
				return accessors.Remover; | 
						|
			return accessors.Raiser; | 
						|
		} | 
						|
 | 
						|
		public static EntityHandle GetGenericType(this in TypeSpecification ts, MetadataReader metadata) | 
						|
		{ | 
						|
			if (ts.Signature.IsNil) | 
						|
				return default; | 
						|
			// Do a quick scan using BlobReader | 
						|
			var signature = metadata.GetBlobReader(ts.Signature); | 
						|
			// When dealing with FSM implementations, we can safely assume that if it's a type spec, | 
						|
			// it must be a generic type instance. | 
						|
			if (signature.ReadByte() != (byte)SignatureTypeCode.GenericTypeInstance) | 
						|
				return default; | 
						|
			// Skip over the rawTypeKind: value type or class | 
						|
			var rawTypeKind = signature.ReadCompressedInteger(); | 
						|
			if (rawTypeKind < 17 || rawTypeKind > 18) | 
						|
				return default; | 
						|
			// Only read the generic type, ignore the type arguments | 
						|
			return signature.ReadTypeHandle(); | 
						|
		} | 
						|
 | 
						|
		public static EntityHandle GetDeclaringType(this EntityHandle entity, MetadataReader metadata) | 
						|
		{ | 
						|
			switch (entity.Kind) | 
						|
			{ | 
						|
				case HandleKind.TypeDefinition: | 
						|
					var td = metadata.GetTypeDefinition((TypeDefinitionHandle)entity); | 
						|
					return td.GetDeclaringType(); | 
						|
				case HandleKind.TypeReference: | 
						|
					var tr = metadata.GetTypeReference((TypeReferenceHandle)entity); | 
						|
					return tr.GetDeclaringType(); | 
						|
				case HandleKind.TypeSpecification: | 
						|
					var ts = metadata.GetTypeSpecification((TypeSpecificationHandle)entity); | 
						|
					return ts.GetGenericType(metadata).GetDeclaringType(metadata); | 
						|
				case HandleKind.FieldDefinition: | 
						|
					var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)entity); | 
						|
					return fd.GetDeclaringType(); | 
						|
				case HandleKind.MethodDefinition: | 
						|
					var md = metadata.GetMethodDefinition((MethodDefinitionHandle)entity); | 
						|
					return md.GetDeclaringType(); | 
						|
				case HandleKind.MemberReference: | 
						|
					var mr = metadata.GetMemberReference((MemberReferenceHandle)entity); | 
						|
					return mr.Parent; | 
						|
				case HandleKind.EventDefinition: | 
						|
					var ed = metadata.GetEventDefinition((EventDefinitionHandle)entity); | 
						|
					return metadata.GetMethodDefinition(ed.GetAccessors().GetAny()).GetDeclaringType(); | 
						|
				case HandleKind.PropertyDefinition: | 
						|
					var pd = metadata.GetPropertyDefinition((PropertyDefinitionHandle)entity); | 
						|
					return metadata.GetMethodDefinition(pd.GetAccessors().GetAny()).GetDeclaringType(); | 
						|
				case HandleKind.MethodSpecification: | 
						|
					var ms = metadata.GetMethodSpecification((MethodSpecificationHandle)entity); | 
						|
					return ms.Method.GetDeclaringType(metadata); | 
						|
				default: | 
						|
					throw new ArgumentOutOfRangeException(); | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		public static TypeReferenceHandle GetDeclaringType(this in TypeReference tr) | 
						|
		{ | 
						|
			switch (tr.ResolutionScope.Kind) | 
						|
			{ | 
						|
				case HandleKind.TypeReference: | 
						|
					return (TypeReferenceHandle)tr.ResolutionScope; | 
						|
				default: | 
						|
					return default(TypeReferenceHandle); | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		public static FullTypeName GetFullTypeName(this EntityHandle handle, MetadataReader reader) | 
						|
		{ | 
						|
			if (handle.IsNil) | 
						|
				throw new ArgumentNullException(nameof(handle)); | 
						|
			switch (handle.Kind) | 
						|
			{ | 
						|
				case HandleKind.TypeDefinition: | 
						|
					return ((TypeDefinitionHandle)handle).GetFullTypeName(reader); | 
						|
				case HandleKind.TypeReference: | 
						|
					return ((TypeReferenceHandle)handle).GetFullTypeName(reader); | 
						|
				case HandleKind.TypeSpecification: | 
						|
					return ((TypeSpecificationHandle)handle).GetFullTypeName(reader); | 
						|
				default: | 
						|
					throw new ArgumentOutOfRangeException(); | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		public static bool IsKnownType(this EntityHandle handle, MetadataReader reader, | 
						|
			KnownTypeCode knownType) | 
						|
		{ | 
						|
			return IsKnownType(handle, reader, KnownTypeReference.Get(knownType).TypeName); | 
						|
		} | 
						|
 | 
						|
		internal static bool IsKnownType(this EntityHandle handle, MetadataReader reader, | 
						|
			KnownAttribute knownType) | 
						|
		{ | 
						|
			return IsKnownType(handle, reader, knownType.GetTypeName()); | 
						|
		} | 
						|
 | 
						|
		private static bool IsKnownType(EntityHandle handle, MetadataReader reader, TopLevelTypeName knownType) | 
						|
		{ | 
						|
			if (handle.IsNil) | 
						|
				return false; | 
						|
			StringHandle nameHandle, namespaceHandle; | 
						|
			try | 
						|
			{ | 
						|
				switch (handle.Kind) | 
						|
				{ | 
						|
					case HandleKind.TypeReference: | 
						|
						var tr = reader.GetTypeReference((TypeReferenceHandle)handle); | 
						|
						// ignore exported and nested types | 
						|
						if (tr.ResolutionScope.IsNil || tr.ResolutionScope.Kind == HandleKind.TypeReference) | 
						|
							return false; | 
						|
						nameHandle = tr.Name; | 
						|
						namespaceHandle = tr.Namespace; | 
						|
						break; | 
						|
					case HandleKind.TypeDefinition: | 
						|
						var td = reader.GetTypeDefinition((TypeDefinitionHandle)handle); | 
						|
						if (td.IsNested) | 
						|
							return false; | 
						|
						nameHandle = td.Name; | 
						|
						namespaceHandle = td.Namespace; | 
						|
						break; | 
						|
					case HandleKind.TypeSpecification: | 
						|
						var ts = reader.GetTypeSpecification((TypeSpecificationHandle)handle); | 
						|
						var blob = reader.GetBlobReader(ts.Signature); | 
						|
						return SignatureIsKnownType(reader, knownType, ref blob); | 
						|
					default: | 
						|
						return false; | 
						|
				} | 
						|
			} | 
						|
			catch (BadImageFormatException) | 
						|
			{ | 
						|
				// ignore bad metadata when trying to resolve ResolutionScope et al. | 
						|
				return false; | 
						|
			} | 
						|
			if (knownType.TypeParameterCount == 0) | 
						|
			{ | 
						|
				if (!reader.StringComparer.Equals(nameHandle, knownType.Name)) | 
						|
					return false; | 
						|
			} | 
						|
			else | 
						|
			{ | 
						|
				string name = reader.GetString(nameHandle); | 
						|
				name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(name, out int typeParameterCount); | 
						|
				if (typeParameterCount != knownType.TypeParameterCount || name != knownType.Name) | 
						|
					return false; | 
						|
			} | 
						|
			if (namespaceHandle.IsNil) | 
						|
			{ | 
						|
				return knownType.Namespace.Length == 0; | 
						|
			} | 
						|
			else | 
						|
			{ | 
						|
				return reader.StringComparer.Equals(namespaceHandle, knownType.Namespace); | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		private static bool SignatureIsKnownType(MetadataReader reader, TopLevelTypeName knownType, ref BlobReader blob) | 
						|
		{ | 
						|
			if (!blob.TryReadCompressedInteger(out int typeCode)) | 
						|
				return false; | 
						|
			switch (typeCode) | 
						|
			{ | 
						|
				case 0x1: // ELEMENT_TYPE_VOID | 
						|
					return knownType.IsKnownType(KnownTypeCode.Void); | 
						|
				case 0x2: // ELEMENT_TYPE_BOOLEAN  | 
						|
					return knownType.IsKnownType(KnownTypeCode.Boolean); | 
						|
				case 0x3: // ELEMENT_TYPE_CHAR  | 
						|
					return knownType.IsKnownType(KnownTypeCode.Char); | 
						|
				case 0x4: // ELEMENT_TYPE_I1  | 
						|
					return knownType.IsKnownType(KnownTypeCode.SByte); | 
						|
				case 0x5: // ELEMENT_TYPE_U1 | 
						|
					return knownType.IsKnownType(KnownTypeCode.Byte); | 
						|
				case 0x6: // ELEMENT_TYPE_I2 | 
						|
					return knownType.IsKnownType(KnownTypeCode.Int16); | 
						|
				case 0x7: // ELEMENT_TYPE_U2 | 
						|
					return knownType.IsKnownType(KnownTypeCode.UInt16); | 
						|
				case 0x8: // ELEMENT_TYPE_I4 | 
						|
					return knownType.IsKnownType(KnownTypeCode.Int32); | 
						|
				case 0x9: // ELEMENT_TYPE_U4 | 
						|
					return knownType.IsKnownType(KnownTypeCode.UInt32); | 
						|
				case 0xA: // ELEMENT_TYPE_I8 | 
						|
					return knownType.IsKnownType(KnownTypeCode.Int64); | 
						|
				case 0xB: // ELEMENT_TYPE_U8 | 
						|
					return knownType.IsKnownType(KnownTypeCode.UInt64); | 
						|
				case 0xC: // ELEMENT_TYPE_R4 | 
						|
					return knownType.IsKnownType(KnownTypeCode.Single); | 
						|
				case 0xD: // ELEMENT_TYPE_R8 | 
						|
					return knownType.IsKnownType(KnownTypeCode.Double); | 
						|
				case 0xE: // ELEMENT_TYPE_STRING | 
						|
					return knownType.IsKnownType(KnownTypeCode.String); | 
						|
				case 0x16: // ELEMENT_TYPE_TYPEDBYREF | 
						|
					return knownType.IsKnownType(KnownTypeCode.TypedReference); | 
						|
				case 0x18: // ELEMENT_TYPE_I | 
						|
					return knownType.IsKnownType(KnownTypeCode.IntPtr); | 
						|
				case 0x19: // ELEMENT_TYPE_U | 
						|
					return knownType.IsKnownType(KnownTypeCode.UIntPtr); | 
						|
				case 0x1C: // ELEMENT_TYPE_OBJECT | 
						|
					return knownType.IsKnownType(KnownTypeCode.Object); | 
						|
				case 0xF: // ELEMENT_TYPE_PTR  | 
						|
				case 0x10: // ELEMENT_TYPE_BYREF  | 
						|
				case 0x45: // ELEMENT_TYPE_PINNED | 
						|
				case 0x1D: // ELEMENT_TYPE_SZARRAY | 
						|
				case 0x1B: // ELEMENT_TYPE_FNPTR  | 
						|
				case 0x14: // ELEMENT_TYPE_ARRAY  | 
						|
					return false; | 
						|
				case 0x1F: // ELEMENT_TYPE_CMOD_REQD  | 
						|
				case 0x20: // ELEMENT_TYPE_CMOD_OPT  | 
						|
						   // modifier | 
						|
					blob.ReadTypeHandle(); // skip modifier | 
						|
					return SignatureIsKnownType(reader, knownType, ref blob); | 
						|
				case 0x15: // ELEMENT_TYPE_GENERICINST  | 
						|
						   // generic type | 
						|
					return SignatureIsKnownType(reader, knownType, ref blob); | 
						|
				case 0x13: // ELEMENT_TYPE_VAR | 
						|
				case 0x1E: // ELEMENT_TYPE_MVAR  | 
						|
						   // index | 
						|
					return false; | 
						|
				case 0x11: // ELEMENT_TYPE_VALUETYPE | 
						|
				case 0x12: // ELEMENT_TYPE_CLASS | 
						|
					return IsKnownType(blob.ReadTypeHandle(), reader, knownType); | 
						|
				default: | 
						|
					return false; | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		public static FullTypeName GetFullTypeName(this TypeSpecificationHandle handle, MetadataReader reader) | 
						|
		{ | 
						|
			if (handle.IsNil) | 
						|
				throw new ArgumentNullException(nameof(handle)); | 
						|
			var ts = reader.GetTypeSpecification(handle); | 
						|
			return ts.DecodeSignature(new Metadata.FullTypeNameSignatureDecoder(reader), default(Unit)); | 
						|
		} | 
						|
 | 
						|
		public static FullTypeName GetFullTypeName(this TypeReferenceHandle handle, MetadataReader reader) | 
						|
		{ | 
						|
			if (handle.IsNil) | 
						|
				throw new ArgumentNullException(nameof(handle)); | 
						|
			var tr = reader.GetTypeReference(handle); | 
						|
			string name; | 
						|
			try | 
						|
			{ | 
						|
				name = reader.GetString(tr.Name); | 
						|
			} | 
						|
			catch (BadImageFormatException) | 
						|
			{ | 
						|
				name = $"TR{reader.GetToken(handle):x8}"; | 
						|
			} | 
						|
			name = ReflectionHelper.SplitTypeParameterCountFromReflectionName( | 
						|
				name, out var typeParameterCount); | 
						|
			TypeReferenceHandle declaringTypeHandle; | 
						|
			try | 
						|
			{ | 
						|
				declaringTypeHandle = tr.GetDeclaringType(); | 
						|
			} | 
						|
			catch (BadImageFormatException) | 
						|
			{ | 
						|
				declaringTypeHandle = default; | 
						|
			} | 
						|
			if (declaringTypeHandle.IsNil) | 
						|
			{ | 
						|
				string ns; | 
						|
				try | 
						|
				{ | 
						|
					ns = tr.Namespace.IsNil ? "" : reader.GetString(tr.Namespace); | 
						|
				} | 
						|
				catch (BadImageFormatException) | 
						|
				{ | 
						|
					ns = ""; | 
						|
				} | 
						|
				return new FullTypeName(new TopLevelTypeName(ns, name, typeParameterCount)); | 
						|
			} | 
						|
			else | 
						|
			{ | 
						|
				return declaringTypeHandle.GetFullTypeName(reader).NestedType(name, typeParameterCount); | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		public static FullTypeName GetFullTypeName(this TypeDefinitionHandle handle, MetadataReader reader) | 
						|
		{ | 
						|
			if (handle.IsNil) | 
						|
				throw new ArgumentNullException(nameof(handle)); | 
						|
			return reader.GetTypeDefinition(handle).GetFullTypeName(reader); | 
						|
		} | 
						|
 | 
						|
		public static FullTypeName GetFullTypeName(this TypeDefinition td, MetadataReader reader) | 
						|
		{ | 
						|
			TypeDefinitionHandle declaringTypeHandle; | 
						|
			string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName( | 
						|
				reader.GetString(td.Name), out var typeParameterCount); | 
						|
			if ((declaringTypeHandle = td.GetDeclaringType()).IsNil) | 
						|
			{ | 
						|
				string @namespace = td.Namespace.IsNil ? "" : reader.GetString(td.Namespace); | 
						|
				return new FullTypeName(new TopLevelTypeName(@namespace, name, typeParameterCount)); | 
						|
			} | 
						|
			else | 
						|
			{ | 
						|
				return declaringTypeHandle.GetFullTypeName(reader).NestedType(name, typeParameterCount); | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		public static FullTypeName GetFullTypeName(this ExportedType type, MetadataReader metadata) | 
						|
		{ | 
						|
			string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName( | 
						|
				metadata.GetString(type.Name), out int typeParameterCount); | 
						|
			if (type.Implementation.Kind == HandleKind.ExportedType) | 
						|
			{ | 
						|
				var outerType = metadata.GetExportedType((ExportedTypeHandle)type.Implementation); | 
						|
				return outerType.GetFullTypeName(metadata).NestedType(name, typeParameterCount); | 
						|
			} | 
						|
			else | 
						|
			{ | 
						|
				string ns = type.Namespace.IsNil ? "" : metadata.GetString(type.Namespace); | 
						|
				return new TopLevelTypeName(ns, name, typeParameterCount); | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		public static bool IsAnonymousType(this TypeDefinition type, MetadataReader metadata) | 
						|
		{ | 
						|
			string name = metadata.GetString(type.Name); | 
						|
			if (type.Namespace.IsNil && type.HasGeneratedName(metadata) | 
						|
				&& (name.Contains("AnonType") || name.Contains("AnonymousType"))) | 
						|
			{ | 
						|
				return type.IsCompilerGenerated(metadata); | 
						|
			} | 
						|
			return false; | 
						|
		} | 
						|
 | 
						|
		#region HasGeneratedName | 
						|
 | 
						|
		public static bool IsGeneratedName(this StringHandle handle, MetadataReader metadata) | 
						|
		{ | 
						|
			return !handle.IsNil | 
						|
				&& (metadata.GetString(handle).StartsWith("<", StringComparison.Ordinal) | 
						|
				|| metadata.GetString(handle).Contains("$")); | 
						|
		} | 
						|
 | 
						|
		public static bool HasGeneratedName(this MethodDefinitionHandle handle, MetadataReader metadata) | 
						|
		{ | 
						|
			return metadata.GetMethodDefinition(handle).Name.IsGeneratedName(metadata); | 
						|
		} | 
						|
 | 
						|
		public static bool HasGeneratedName(this TypeDefinitionHandle handle, MetadataReader metadata) | 
						|
		{ | 
						|
			return metadata.GetTypeDefinition(handle).Name.IsGeneratedName(metadata); | 
						|
		} | 
						|
 | 
						|
		public static bool HasGeneratedName(this TypeDefinition type, MetadataReader metadata) | 
						|
		{ | 
						|
			return type.Name.IsGeneratedName(metadata); | 
						|
		} | 
						|
 | 
						|
		public static bool HasGeneratedName(this FieldDefinitionHandle handle, MetadataReader metadata) | 
						|
		{ | 
						|
			return metadata.GetFieldDefinition(handle).Name.IsGeneratedName(metadata); | 
						|
		} | 
						|
 | 
						|
		#endregion | 
						|
 | 
						|
		#region IsCompilerGenerated | 
						|
 | 
						|
		public static bool IsCompilerGenerated(this MethodDefinitionHandle handle, MetadataReader metadata) | 
						|
		{ | 
						|
			return metadata.GetMethodDefinition(handle).IsCompilerGenerated(metadata); | 
						|
		} | 
						|
 | 
						|
		public static bool IsCompilerGeneratedOrIsInCompilerGeneratedClass(this MethodDefinitionHandle handle, | 
						|
			MetadataReader metadata) | 
						|
		{ | 
						|
			MethodDefinition method = metadata.GetMethodDefinition(handle); | 
						|
			if (method.IsCompilerGenerated(metadata)) | 
						|
				return true; | 
						|
			TypeDefinitionHandle declaringTypeHandle = method.GetDeclaringType(); | 
						|
			if (!declaringTypeHandle.IsNil && declaringTypeHandle.IsCompilerGenerated(metadata)) | 
						|
				return true; | 
						|
			return false; | 
						|
		} | 
						|
 | 
						|
		public static bool IsCompilerGeneratedOrIsInCompilerGeneratedClass(this TypeDefinitionHandle handle, | 
						|
			MetadataReader metadata) | 
						|
		{ | 
						|
			TypeDefinition type = metadata.GetTypeDefinition(handle); | 
						|
			if (type.IsCompilerGenerated(metadata)) | 
						|
				return true; | 
						|
			TypeDefinitionHandle declaringTypeHandle = type.GetDeclaringType(); | 
						|
			if (!declaringTypeHandle.IsNil && declaringTypeHandle.IsCompilerGenerated(metadata)) | 
						|
				return true; | 
						|
			return false; | 
						|
		} | 
						|
 | 
						|
		public static bool IsCompilerGenerated(this MethodDefinition method, MetadataReader metadata) | 
						|
		{ | 
						|
			return method.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.CompilerGenerated); | 
						|
		} | 
						|
 | 
						|
		public static bool IsCompilerGenerated(this FieldDefinitionHandle handle, MetadataReader metadata) | 
						|
		{ | 
						|
			return metadata.GetFieldDefinition(handle).IsCompilerGenerated(metadata); | 
						|
		} | 
						|
 | 
						|
		public static bool IsCompilerGenerated(this FieldDefinition field, MetadataReader metadata) | 
						|
		{ | 
						|
			return field.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.CompilerGenerated); | 
						|
		} | 
						|
 | 
						|
		public static bool IsCompilerGenerated(this TypeDefinitionHandle handle, MetadataReader metadata) | 
						|
		{ | 
						|
			return metadata.GetTypeDefinition(handle).IsCompilerGenerated(metadata); | 
						|
		} | 
						|
 | 
						|
		public static bool IsCompilerGenerated(this TypeDefinition type, MetadataReader metadata) | 
						|
		{ | 
						|
			return type.GetCustomAttributes().HasKnownAttribute(metadata, KnownAttribute.CompilerGenerated); | 
						|
		} | 
						|
 | 
						|
		#endregion | 
						|
 | 
						|
		#region Attribute extensions | 
						|
		/// <summary> | 
						|
		/// Gets the type of the attribute. | 
						|
		/// </summary> | 
						|
		public static EntityHandle GetAttributeType(this SRM.CustomAttribute attribute, MetadataReader reader) | 
						|
		{ | 
						|
			switch (attribute.Constructor.Kind) | 
						|
			{ | 
						|
				case HandleKind.MethodDefinition: | 
						|
					var md = reader.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor); | 
						|
					return md.GetDeclaringType(); | 
						|
				case HandleKind.MemberReference: | 
						|
					var mr = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor); | 
						|
					return mr.Parent; | 
						|
				default: | 
						|
					throw new BadImageFormatException("Unexpected token kind for attribute constructor: " | 
						|
						+ attribute.Constructor.Kind); | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		public static bool HasKnownAttribute(this CustomAttributeHandleCollection customAttributes, | 
						|
			MetadataReader metadata, KnownAttribute type) | 
						|
		{ | 
						|
			foreach (var handle in customAttributes) | 
						|
			{ | 
						|
				var customAttribute = metadata.GetCustomAttribute(handle); | 
						|
				if (customAttribute.IsKnownAttribute(metadata, type)) | 
						|
					return true; | 
						|
			} | 
						|
			return false; | 
						|
		} | 
						|
 | 
						|
		internal static bool IsKnownAttribute(this SRM.CustomAttribute attr, MetadataReader metadata, | 
						|
			KnownAttribute attrType) | 
						|
		{ | 
						|
			return attr.GetAttributeType(metadata).IsKnownType(metadata, attrType); | 
						|
		} | 
						|
 | 
						|
		public static Nullability? GetNullableContext(this CustomAttributeHandleCollection customAttributes, | 
						|
			MetadataReader metadata) | 
						|
		{ | 
						|
			foreach (var handle in customAttributes) | 
						|
			{ | 
						|
				var customAttribute = metadata.GetCustomAttribute(handle); | 
						|
				if (customAttribute.IsKnownAttribute(metadata, KnownAttribute.NullableContext)) | 
						|
				{ | 
						|
					// Decode  | 
						|
					CustomAttributeValue<IType> value; | 
						|
					try | 
						|
					{ | 
						|
						value = customAttribute.DecodeValue( | 
						|
							Metadata.MetadataExtensions.MinimalAttributeTypeProvider); | 
						|
					} | 
						|
					catch (BadImageFormatException) | 
						|
					{ | 
						|
						continue; | 
						|
					} | 
						|
					catch (Metadata.EnumUnderlyingTypeResolveException) | 
						|
					{ | 
						|
						continue; | 
						|
					} | 
						|
					if (value.FixedArguments.Length == 1 && value.FixedArguments[0].Value is byte b && b <= 2) | 
						|
					{ | 
						|
						return (Nullability)b; | 
						|
					} | 
						|
				} | 
						|
			} | 
						|
			return null; | 
						|
		} | 
						|
		#endregion | 
						|
 | 
						|
		public static unsafe BlobReader GetInitialValue(this FieldDefinition field, PEReader pefile, | 
						|
			ICompilation typeSystem) | 
						|
		{ | 
						|
			if (!field.HasFlag(FieldAttributes.HasFieldRVA)) | 
						|
				return default; | 
						|
			int rva = field.GetRelativeVirtualAddress(); | 
						|
			if (rva == 0) | 
						|
				return default; | 
						|
			int size = field.DecodeSignature(new FieldValueSizeDecoder(typeSystem), default); | 
						|
			var sectionData = pefile.GetSectionData(rva); | 
						|
			if (sectionData.Length == 0 && size != 0) | 
						|
				throw new BadImageFormatException($"Field data (rva=0x{rva:x}) could not be found" | 
						|
					+ "in any section!"); | 
						|
			if (size < 0 || size > sectionData.Length) | 
						|
				throw new BadImageFormatException($"Invalid size {size} for field data!"); | 
						|
			return sectionData.GetReader(0, size); | 
						|
		} | 
						|
 | 
						|
		sealed class FieldValueSizeDecoder : ISignatureTypeProvider<int, GenericContext> | 
						|
		{ | 
						|
			readonly MetadataModule module; | 
						|
			readonly int pointerSize; | 
						|
 | 
						|
			public FieldValueSizeDecoder(ICompilation typeSystem = null) | 
						|
			{ | 
						|
				this.module = (MetadataModule)typeSystem?.MainModule; | 
						|
				if (module == null) | 
						|
					this.pointerSize = IntPtr.Size; | 
						|
				else | 
						|
					this.pointerSize = module.PEFile.Reader.PEHeaders.PEHeader.Magic == PEMagic.PE32 ? 4 : 8; | 
						|
			} | 
						|
 | 
						|
			public int GetArrayType(int elementType, ArrayShape shape) => | 
						|
				GetPrimitiveType(PrimitiveTypeCode.Object); | 
						|
			public int GetSZArrayType(int elementType) => GetPrimitiveType(PrimitiveTypeCode.Object); | 
						|
			public int GetByReferenceType(int elementType) => pointerSize; | 
						|
			public int GetFunctionPointerType(MethodSignature<int> signature) => pointerSize; | 
						|
			public int GetGenericInstantiation(int genericType, ImmutableArray<int> typeArguments) | 
						|
				=> genericType; | 
						|
			public int GetGenericMethodParameter(GenericContext genericContext, int index) => 0; | 
						|
			public int GetGenericTypeParameter(GenericContext genericContext, int index) => 0; | 
						|
			public int GetModifiedType(int modifier, int unmodifiedType, bool isRequired) => unmodifiedType; | 
						|
			public int GetPinnedType(int elementType) => elementType; | 
						|
			public int GetPointerType(int elementType) => pointerSize; | 
						|
 | 
						|
			public int GetPrimitiveType(PrimitiveTypeCode typeCode) | 
						|
			{ | 
						|
				switch (typeCode) | 
						|
				{ | 
						|
					case PrimitiveTypeCode.Boolean: | 
						|
					case PrimitiveTypeCode.Byte: | 
						|
					case PrimitiveTypeCode.SByte: | 
						|
						return 1; | 
						|
					case PrimitiveTypeCode.Char: | 
						|
					case PrimitiveTypeCode.Int16: | 
						|
					case PrimitiveTypeCode.UInt16: | 
						|
						return 2; | 
						|
					case PrimitiveTypeCode.Int32: | 
						|
					case PrimitiveTypeCode.UInt32: | 
						|
					case PrimitiveTypeCode.Single: | 
						|
						return 4; | 
						|
					case PrimitiveTypeCode.Int64: | 
						|
					case PrimitiveTypeCode.UInt64: | 
						|
					case PrimitiveTypeCode.Double: | 
						|
						return 8; | 
						|
					case PrimitiveTypeCode.IntPtr: | 
						|
					case PrimitiveTypeCode.UIntPtr: | 
						|
						return pointerSize; | 
						|
					default: | 
						|
						return 0; | 
						|
				} | 
						|
			} | 
						|
 | 
						|
			public int GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, | 
						|
				byte rawTypeKind) | 
						|
			{ | 
						|
				var td = reader.GetTypeDefinition(handle); | 
						|
				return td.GetLayout().Size; | 
						|
			} | 
						|
 | 
						|
			public int GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, | 
						|
				byte rawTypeKind) | 
						|
			{ | 
						|
				var typeDef = module?.ResolveType(handle, new GenericContext()).GetDefinition(); | 
						|
				if (typeDef == null || typeDef.MetadataToken.IsNil) | 
						|
					return 0; | 
						|
				reader = typeDef.ParentModule.PEFile.Metadata; | 
						|
				var td = reader.GetTypeDefinition((TypeDefinitionHandle)typeDef.MetadataToken); | 
						|
				return td.GetLayout().Size; | 
						|
			} | 
						|
 | 
						|
			public int GetTypeFromSpecification(MetadataReader reader, GenericContext genericContext, | 
						|
				TypeSpecificationHandle handle, byte rawTypeKind) | 
						|
			{ | 
						|
				return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext); | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		public static EntityHandle GetBaseTypeOrNil(this TypeDefinition definition) | 
						|
		{ | 
						|
			try | 
						|
			{ | 
						|
				return definition.BaseType; | 
						|
			} | 
						|
			catch (BadImageFormatException) | 
						|
			{ | 
						|
				return default; | 
						|
			} | 
						|
		} | 
						|
 | 
						|
		public static string ToILSyntax(this SignatureCallingConvention callConv) | 
						|
		{ | 
						|
			return callConv switch { | 
						|
				SignatureCallingConvention.Default => "default", | 
						|
				SignatureCallingConvention.CDecl => "unmanaged cdecl", | 
						|
				SignatureCallingConvention.StdCall => "unmanaged stdcall", | 
						|
				SignatureCallingConvention.ThisCall => "unmanaged thiscall", | 
						|
				SignatureCallingConvention.FastCall => "unmanaged fastcall", | 
						|
				SignatureCallingConvention.VarArgs => "vararg", | 
						|
				SignatureCallingConvention.Unmanaged => "unmanaged", | 
						|
				_ => callConv.ToString().ToLowerInvariant() | 
						|
			}; | 
						|
		} | 
						|
	} | 
						|
}
 | 
						|
 |