IMethod ResolveMethodDefinition(MethodDefinitionHandle methodDefHandle, bool expandVarArgs)
        {
            var method = GetDefinition(methodDefHandle);

            if (expandVarArgs && method.Parameters.LastOrDefault()?.Type.Kind == TypeKind.ArgList)
            {
                method = new VarArgInstanceMethod(method, EmptyList <IType> .Instance);
            }
            return(method);
        }
        /// <summary>
        /// Resolves a method reference.
        /// </summary>
        /// <remarks>
        /// Class type arguments are provided by the declaring type stored in the memberRef.
        /// Method type arguments are provided by the caller.
        /// </remarks>
        IMethod ResolveMethodReference(MemberReferenceHandle memberRefHandle, GenericContext context, IReadOnlyList <IType> methodTypeArguments = null, bool expandVarArgs = true)
        {
            var memberRef = metadata.GetMemberReference(memberRefHandle);

            Debug.Assert(memberRef.GetKind() == MemberReferenceKind.Method);
            MethodSignature <IType> signature;
            IReadOnlyList <IType>   classTypeArguments = null;
            IMethod method;

            if (memberRef.Parent.Kind == HandleKind.MethodDefinition)
            {
                method    = ResolveMethodDefinition((MethodDefinitionHandle)memberRef.Parent, expandVarArgs: false);
                signature = memberRef.DecodeMethodSignature(TypeProvider, context);
            }
            else
            {
                var declaringType           = ResolveDeclaringType(memberRef.Parent, context);
                var declaringTypeDefinition = declaringType.GetDefinition();
                if (declaringType.TypeArguments.Count > 0)
                {
                    classTypeArguments = declaringType.TypeArguments;
                }
                // Note: declaringType might be parameterized, but the signature is for the original method definition.
                // We'll have to search the member directly on declaringTypeDefinition.
                string name = metadata.GetString(memberRef.Name);
                signature = memberRef.DecodeMethodSignature(TypeProvider,
                                                            new GenericContext(declaringTypeDefinition?.TypeParameters));
                if (declaringTypeDefinition != null)
                {
                    // Find the set of overloads to search:
                    IEnumerable <IMethod> methods;
                    if (name == ".ctor")
                    {
                        methods = declaringTypeDefinition.GetConstructors();
                    }
                    else if (name == ".cctor")
                    {
                        methods = declaringTypeDefinition.Methods.Where(m => m.IsConstructor && m.IsStatic);
                    }
                    else
                    {
                        methods = declaringTypeDefinition.GetMethods(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers)
                                  .Concat(declaringTypeDefinition.GetAccessors(m => m.Name == name, GetMemberOptions.IgnoreInheritedMembers));
                    }
                    // Determine the expected parameters from the signature:
                    ImmutableArray <IType> parameterTypes;
                    if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs)
                    {
                        parameterTypes = signature.ParameterTypes
                                         .Take(signature.RequiredParameterCount)
                                         .Concat(new[] { SpecialType.ArgList })
                                         .ToImmutableArray();
                    }
                    else
                    {
                        parameterTypes = signature.ParameterTypes;
                    }
                    // Search for the matching method:
                    method = null;
                    foreach (var m in methods)
                    {
                        if (m.TypeParameters.Count != signature.GenericParameterCount)
                        {
                            continue;
                        }
                        if (CompareSignatures(m.Parameters, parameterTypes) && CompareTypes(m.ReturnType, signature.ReturnType))
                        {
                            method = m;
                            break;
                        }
                    }
                }
                else
                {
                    method = null;
                }
                if (method == null)
                {
                    method = CreateFakeMethod(declaringType, name, signature);
                }
            }
            if (classTypeArguments != null || methodTypeArguments != null)
            {
                method = method.Specialize(new TypeParameterSubstitution(classTypeArguments, methodTypeArguments));
            }
            if (expandVarArgs && signature.Header.CallingConvention == SignatureCallingConvention.VarArgs)
            {
                method = new VarArgInstanceMethod(method, signature.ParameterTypes.Skip(signature.RequiredParameterCount));
            }
            return(method);
        }
        public bool Equals(IMember obj, TypeVisitor typeNormalization)
        {
            VarArgInstanceMethod other = obj as VarArgInstanceMethod;

            return(other != null && baseMethod.Equals(other.baseMethod, typeNormalization));
        }
        public override bool Equals(object obj)
        {
            VarArgInstanceMethod other = obj as VarArgInstanceMethod;

            return(other != null && baseMethod.Equals(other.baseMethod));
        }