using System;
using System.Linq;
using System.Reflection;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace StardewModdingAPI.AssemblyRewriters.Framework
{
/// Base class for a method finder.
public abstract class BaseMethodFinder : IInstructionFinder
{
/*********
** Accessors
*********/
/// A brief noun phrase indicating what the instruction finder matches.
public abstract string NounPhrase { get; }
/*********
** Public methods
*********/
/// Get whether a CIL instruction matches.
/// The IL instruction.
/// Whether the mod was compiled on a different platform.
public bool IsMatch(Instruction instruction, bool platformChanged)
{
if (instruction.OpCode != OpCodes.Call && instruction.OpCode != OpCodes.Callvirt)
return false; // not a method reference
return this.IsMatch(instruction, (MethodReference)instruction.Operand, platformChanged);
}
/*********
** Protected methods
*********/
/// Get whether a method reference should be rewritten.
/// The IL instruction.
/// The method reference.
/// Whether the mod was compiled on a different platform.
protected abstract bool IsMatch(Instruction instruction, MethodReference methodRef, bool platformChanged);
/// Get whether a method definition matches the signature expected by a method reference.
/// The method definition.
/// The method reference.
protected bool HasMatchingSignature(MethodInfo definition, MethodReference reference)
{
// same name
if (definition.Name != reference.Name)
return false;
// same arguments
ParameterInfo[] definitionParameters = definition.GetParameters();
ParameterDefinition[] referenceParameters = reference.Parameters.ToArray();
if (referenceParameters.Length != definitionParameters.Length)
return false;
for (int i = 0; i < referenceParameters.Length; i++)
{
if (!RewriteHelper.IsMatchingType(definitionParameters[i].ParameterType, referenceParameters[i].ParameterType))
return false;
}
return true;
}
/// Get whether a type has a method whose signature matches the one expected by a method reference.
/// The type to check.
/// The method reference.
protected bool HasMatchingSignature(Type type, MethodReference reference)
{
return type
.GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public)
.Any(method => this.HasMatchingSignature(method, reference));
}
}
}