Skip to content

Commit

Permalink
Add bool __runOriginal patch parameter; closes #7
Browse files Browse the repository at this point in the history
  • Loading branch information
ghorsington committed Jun 30, 2020
1 parent 188873c commit 3df0826
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 1 deletion.
14 changes: 13 additions & 1 deletion Harmony/Internal/Patching/HarmonyManipulator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ internal static class HarmonyManipulator
private static readonly string INSTANCE_PARAM = "__instance";

private static readonly string ORIGINAL_METHOD_PARAM = "__originalMethod";
private static readonly string RUN_ORIGINAL_PARAM = "__runOriginal";
private static readonly string RESULT_VAR = "__result";
private static readonly string STATE_VAR = "__state";
private static readonly string EXCEPTION_VAR = "__exception";
Expand Down Expand Up @@ -216,9 +217,20 @@ private static ILEmitter.Label MakeReturnLabel(ILEmitter il)
returnValueVar = variables[RESULT_VAR] = retVal == typeof(void) ? null : il.DeclareVariable(retVal);
}

bool CanModifyControlFlow()
{
// A prefix that can modify control flow has one of the following:
// * It returns a boolean
// * It declares bool __runOriginal
return prefixes.Any(p => p.ReturnType == typeof(bool) ||
p.GetParameters()
.Any(pp => pp.Name == RUN_ORIGINAL_PARAM &&
pp.ParameterType.OpenRefType() == typeof(bool)));
}

// Flag to check if the orignal method should be run (or was run)
// Only present if method has a return value and there are prefixes that modify control flow
var runOriginal = prefixes.Any(p => p.ReturnType == typeof(bool))
var runOriginal = variables[RUN_ORIGINAL_PARAM] = CanModifyControlFlow()
? il.DeclareVariable(typeof(bool))
: null;

Expand Down
15 changes: 15 additions & 0 deletions HarmonyTests/Patching/Assets/PatchClasses.cs
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,21 @@ public List<string> FizzBuzz()
}
}

class Class11PrefixPatches
{
public static bool runOriginal = true;

public static void Prefix1(ref bool __runOriginal)
{
__runOriginal = false;
}

public static void Prefix2(bool __runOriginal)
{
runOriginal = __runOriginal;
}
}

// disabled - see test case
/*
public class ClassExceptionFilter
Expand Down
30 changes: 30 additions & 0 deletions HarmonyTests/Patching/StaticPatches.cs
Original file line number Diff line number Diff line change
Expand Up @@ -266,5 +266,35 @@ public void TestMethod10()
Assert.IsTrue(Class10Patch.postfixed);
Assert.IsTrue(Class10Patch.originalResult);
}

[Test]
public void TestSkipOriginalParam()
{
var originalClass = typeof(Class11);
var originalMethod = originalClass.GetMethod("TestMethod");
Assert.NotNull(originalMethod);

var patchClass = typeof(Class11PrefixPatches);
var prefix1 = patchClass.GetMethod("Prefix1");
Assert.NotNull(prefix1);
var prefix2 = patchClass.GetMethod("Prefix2");
Assert.NotNull(prefix2);

var instance = new Harmony("SkipOriginalParam");
Assert.NotNull(instance);

var patcher = new PatchProcessor(instance, originalMethod);
patcher.AddPrefix(prefix1);
patcher.Patch();

var patcher2 = new PatchProcessor(instance, originalMethod);
patcher2.AddPrefix(prefix2);
patcher2.Patch();

var testClass = new Class11();
testClass.TestMethod(0);
Assert.IsFalse(testClass.originalMethodRan);
Assert.IsFalse(Class11PrefixPatches.runOriginal);
}
}
}

0 comments on commit 3df0826

Please sign in to comment.