clean up message test a bit

This commit is contained in:
JohnCorby 2022-01-08 02:39:32 -08:00
parent 4078df7b6e
commit 3963621771

View File

@ -2,6 +2,7 @@
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Cecil.Rocks;
using MonoMod.Cil;
using QSB.Messaging;
using QSB.Utility;
using System;
@ -34,7 +35,7 @@ namespace QSBTests
foreach (var field in fields)
{
if (!field.Eq(fromField) && !field.Eq(toField) && !field.Eq(objectIdField))
if (!field.GenericEq(fromField) && !field.GenericEq(toField) && !field.GenericEq(objectIdField))
{
constructor.CheckUses(field, Util.UseType.Store);
}
@ -46,60 +47,45 @@ namespace QSBTests
}
}
internal static class Util
public static partial class Util
{
public const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
public static bool Eq(this MemberReference a, MemberReference b) =>
/// <summary>
/// ignores open vs closed generic type
/// </summary>
public static bool GenericEq(this MemberReference a, MemberReference b) =>
a.DeclaringType.Namespace == b.DeclaringType.Namespace &&
a.DeclaringType.Name == b.DeclaringType.Name &&
a.Name == b.Name;
public static bool IsOp<T>(this Instruction instruction, OpCode opCode, out T operand)
{
if (instruction.OpCode == opCode)
{
operand = (T)instruction.Operand;
return true;
}
operand = default;
return false;
}
public enum UseType { Store, Load };
public enum UseType { Store, Load }
public static void CheckUses(this MethodDefinition method, FieldReference field, UseType useType)
{
var opCode = useType switch
Func<Instruction, bool> matches = useType switch
{
UseType.Store => OpCodes.Stfld,
UseType.Load => OpCodes.Ldfld,
UseType.Store => x => x.MatchStfld(out var f) && f.GenericEq(field),
UseType.Load => x => x.MatchLdfld(out var f) && f.GenericEq(field),
_ => throw new ArgumentOutOfRangeException(nameof(useType), useType, null)
};
while (true)
{
var il = method.Body.Instructions;
var uses = il.Any(x =>
x.IsOp(opCode, out FieldReference f) &&
f.Eq(field)
);
var uses = il.Any(matches);
if (uses)
{
return;
}
var baseMethod = method.GetBaseMethod();
if (baseMethod.Eq(method))
if (baseMethod == method)
{
break;
}
var callsBase = il.Any(x =>
x.IsOp(OpCodes.Call, out MethodReference m) &&
m.Eq(baseMethod)
);
var callsBase = il.Any(x => x.MatchCall(out var m) && m.GenericEq(baseMethod));
if (!callsBase)
{
break;