/* Copyright (C) 2014-2019 de4dot@gmail.com This file is part of dnSpy dnSpy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dnSpy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with dnSpy. If not, see . */ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using dnSpy.Debugger.DotNet.Metadata.Impl; namespace dnSpy.Debugger.DotNet.Metadata { /// /// A .NET method /// public abstract class DmdMethodInfo : DmdMethodBase, IEquatable { /// /// Gets the member type /// public sealed override DmdMemberTypes MemberType => DmdMemberTypes.Method; /// /// Resolves a member reference /// /// true to throw if it doesn't exist, false to return null if it doesn't exist /// public sealed override DmdMemberInfo? ResolveMember(bool throwOnError) => Resolve(throwOnError); /// /// Resolves a method reference /// /// true to throw if it doesn't exist, false to return null if it doesn't exist /// public sealed override DmdMethodBase? ResolveMethodBase(bool throwOnError) => Resolve(throwOnError); /// /// Resolves a method reference and throws if it doesn't exist /// /// public DmdMethodInfo Resolve() => Resolve(throwOnError: true)!; /// /// Resolves a method reference and returns null if it doesn't exist /// /// public DmdMethodInfo? ResolveNoThrow() => Resolve(throwOnError: false); /// /// Resolves a method reference /// /// true to throw if it doesn't exist, false to return null if it doesn't exist /// public abstract DmdMethodInfo? Resolve(bool throwOnError); /// /// Gets the return type /// public abstract DmdType ReturnType { get; } /// /// Gets the return parameter /// public abstract DmdParameterInfo ReturnParameter { get; } /// /// Gets the return type's custom attributes /// public IDmdCustomAttributeProvider ReturnTypeCustomAttributes => ReturnParameter; /// /// true if it contains generic parameters /// public override bool ContainsGenericParameters { get { if (DeclaringType!.ContainsGenericParameters) return true; if (!IsGenericMethod) return false; foreach (var genArg in GetGenericArguments()) { if (genArg.ContainsGenericParameters) return true; } return false; } } /// /// Gets the base method definition or itself if it doesn't override a method /// /// public DmdMethodInfo GetBaseDefinition() { if (!IsVirtual && !IsAbstract) return this; if (DeclaringType!.IsInterface) return this; var method = this; for (;;) { var parentMethod = method.GetParentDefinition(); if (parentMethod is null) { Debug.Assert((object?)ReflectedType == method.ReflectedType); if ((object?)method.DeclaringType == method.ReflectedType) return method; return method.DeclaringType!.GetMethod(method.Module, method.MetadataToken) as DmdMethodInfo ?? throw new InvalidOperationException(); } method = parentMethod; } } /// /// Gets the parent method /// /// internal abstract DmdMethodInfo? GetParentDefinition(); /// /// Gets all generic arguments if it's a generic method /// /// public abstract override ReadOnlyCollection GetGenericArguments(); /// /// Gets the generic method definition /// /// public abstract DmdMethodInfo GetGenericMethodDefinition(); /// /// Creates a generic method /// /// Generic arguments /// public DmdMethodInfo MakeGenericMethod(params DmdType[] typeArguments) => MakeGenericMethod((IList)typeArguments); /// /// Creates a generic method /// /// Generic arguments /// public DmdMethodInfo MakeGenericMethod(params Type[] typeArguments) => MakeGenericMethod((IList)typeArguments); /// /// Creates a generic method /// /// Generic arguments /// public abstract DmdMethodInfo MakeGenericMethod(IList typeArguments); /// /// Creates a generic method /// /// Generic arguments /// public DmdMethodInfo MakeGenericMethod(IList typeArguments) => MakeGenericMethod(typeArguments.ToDmdTypeNoNull(AppDomain)); /// /// Checks if a custom attribute is present /// /// Full name of the custom attribute type /// true to check custom attributes in all base classes /// public sealed override bool IsDefined(string attributeTypeFullName, bool inherit) => CustomAttributesHelper.IsDefined(this, attributeTypeFullName, inherit); /// /// Checks if a custom attribute is present /// /// Custom attribute type /// true to check custom attributes in all base classes /// public sealed override bool IsDefined(DmdType? attributeType, bool inherit) => CustomAttributesHelper.IsDefined(this, attributeType, inherit); /// /// Finds a custom attribute /// /// Full name of the custom attribute type /// true to check custom attributes in all base classes /// public sealed override DmdCustomAttributeData? FindCustomAttribute(string attributeTypeFullName, bool inherit) => CustomAttributesHelper.Find(this, attributeTypeFullName, inherit); /// /// Finds a custom attribute /// /// Custom attribute type /// true to check custom attributes in all base classes /// public sealed override DmdCustomAttributeData? FindCustomAttribute(DmdType? attributeType, bool inherit) => CustomAttributesHelper.Find(this, attributeType, inherit); #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public static bool operator ==(DmdMethodInfo? left, DmdMethodInfo? right) => DmdMemberInfoEqualityComparer.DefaultMember.Equals(left, right); public static bool operator !=(DmdMethodInfo? left, DmdMethodInfo? right) => !DmdMemberInfoEqualityComparer.DefaultMember.Equals(left, right); #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member /// /// Equals() /// /// /// public bool Equals(DmdMethodInfo? other) => DmdMemberInfoEqualityComparer.DefaultMember.Equals(this, other); /// /// Equals() /// /// /// public override bool Equals(object? obj) => Equals(obj as DmdMethodInfo); /// /// GetHashCode() /// /// public override int GetHashCode() => DmdMemberInfoEqualityComparer.DefaultMember.GetHashCode(this); } }