// // Author: // Jb Evain (jbevain@gmail.com) // // Copyright (c) 2008 - 2015 Jb Evain // Copyright (c) 2008 - 2011 Novell, Inc. // // Licensed under the MIT/X11 license. // using MonoFN.Collections.Generic; using System; using System.Text; using System.Threading; namespace MonoFN.Cecil { public class MethodReference : MemberReference, IMethodSignature, IGenericParameterProvider, IGenericContext { internal ParameterDefinitionCollection parameters; private MethodReturnType return_type; internal Collection generic_parameters; public virtual bool HasThis { get; set; } public virtual bool ExplicitThis { get; set; } public virtual MethodCallingConvention CallingConvention { get; set; } public virtual bool HasParameters { get { return !parameters.IsNullOrEmpty(); } } public virtual Collection Parameters { get { if (parameters == null) Interlocked.CompareExchange(ref parameters, new(this), null); return parameters; } } IGenericParameterProvider IGenericContext.Type { get { TypeReference declaring_type = DeclaringType; GenericInstanceType instance = declaring_type as GenericInstanceType; if (instance != null) return instance.ElementType; return declaring_type; } } IGenericParameterProvider IGenericContext.Method { get { return this; } } GenericParameterType IGenericParameterProvider.GenericParameterType { get { return GenericParameterType.Method; } } public virtual bool HasGenericParameters { get { return !generic_parameters.IsNullOrEmpty(); } } public virtual Collection GenericParameters { get { if (generic_parameters == null) Interlocked.CompareExchange(ref generic_parameters, new GenericParameterCollection(this), null); return generic_parameters; } } public TypeReference ReturnType { get { MethodReturnType return_type = MethodReturnType; return return_type != null ? return_type.ReturnType : null; } set { MethodReturnType return_type = MethodReturnType; if (return_type != null) return_type.ReturnType = value; } } public virtual MethodReturnType MethodReturnType { get { return return_type; } set { return_type = value; } } public override string FullName { get { StringBuilder builder = new(); builder.Append(ReturnType.FullName).Append(" ").Append(MemberFullName()); this.MethodSignatureFullName(builder); return builder.ToString(); } } public virtual bool IsGenericInstance { get { return false; } } public override bool ContainsGenericParameter { get { if (ReturnType.ContainsGenericParameter || base.ContainsGenericParameter) return true; if (!HasParameters) return false; Collection parameters = Parameters; for (int i = 0; i < parameters.Count; i++) if (parameters[i].ParameterType.ContainsGenericParameter) return true; return false; } } internal MethodReference() { return_type = new(this); token = new(TokenType.MemberRef); } public MethodReference(string name, TypeReference returnType) : base(name) { Mixin.CheckType(returnType, Mixin.Argument.returnType); return_type = new(this); return_type.ReturnType = returnType; token = new(TokenType.MemberRef); } public MethodReference(string name, TypeReference returnType, TypeReference declaringType) : this(name, returnType) { Mixin.CheckType(declaringType, Mixin.Argument.declaringType); DeclaringType = declaringType; } public virtual MethodReference GetElementMethod() { return this; } protected override IMemberDefinition ResolveDefinition() { return Resolve(); } public new virtual MethodDefinition Resolve() { ModuleDefinition module = Module; if (module == null) throw new NotSupportedException(); return module.Resolve(this); } } internal static partial class Mixin { public static bool IsVarArg(this IMethodSignature self) { return self.CallingConvention == MethodCallingConvention.VarArg; } public static int GetSentinelPosition(this IMethodSignature self) { if (!self.HasParameters) return -1; Collection parameters = self.Parameters; for (int i = 0; i < parameters.Count; i++) if (parameters[i].ParameterType.IsSentinel) return i; return -1; } } }