about summary refs log tree commit diff
path: root/pkgs/games/build-support
diff options
context:
space:
mode:
authoraszlig <aszlig@nix.build>2018-07-18 16:51:44 +0200
committeraszlig <aszlig@nix.build>2018-07-19 06:35:48 +0200
commit3106b5dc491a75c8aa7a3696728aea9cd48d4cb7 (patch)
treeeba37881a0adb428bea6fb4bf2424e312e6f94a0 /pkgs/games/build-support
parente3c58ef839b4939503cc2da8859f92e28aa3b037 (diff)
monogame-patcher: Allow to define specific methods
So far we only matched a substring of a type, which isn't very exact of
course. We also weren't able to specify the method to patch.

Now the methods that are being patched can be specified by using
Type::Method. If it's just Type without a method all the methods of the
type and its subtypes are patched.

I also added a small check to make sure that all of these methods were
found, and if not an error is thrown.

Signed-off-by: aszlig <aszlig@nix.build>
Diffstat (limited to 'pkgs/games/build-support')
-rw-r--r--pkgs/games/build-support/monogame-patcher/src/patcher.cs61
-rw-r--r--pkgs/games/build-support/monogame-patcher/src/test.sh11
2 files changed, 49 insertions, 23 deletions
diff --git a/pkgs/games/build-support/monogame-patcher/src/patcher.cs b/pkgs/games/build-support/monogame-patcher/src/patcher.cs
index bf572d9c..90ed640f 100644
--- a/pkgs/games/build-support/monogame-patcher/src/patcher.cs
+++ b/pkgs/games/build-support/monogame-patcher/src/patcher.cs
@@ -25,6 +25,42 @@ class Command {
         this.module = this.read_module(this.infile, readOnly);
     }
 
+    private IEnumerable<MethodDefinition> get_methods(TypeDefinition td) {
+        return td.NestedTypes
+            .SelectMany(n => this.get_methods(n))
+            .Union(td.Methods);
+    }
+
+    protected IEnumerable<MethodDefinition> getm(IEnumerable<string> types) {
+        var needles = types
+            .Select(t => t.Split(new[] { "::" }, 2, StringSplitOptions.None));
+
+        foreach (var n in needles) {
+            var filtered = this.module.Types.Where(p => p.Name == n[0]);
+            var methods = filtered.SelectMany(t => this.get_methods(t));
+
+            var found = false;
+
+            if (n.Length == 1) {
+                foreach (var m in methods)
+                    yield return m;
+                found = true;
+            } else {
+                foreach (var m in methods) {
+                    if (m.Name == n[1]) {
+                        found = true;
+                        yield return m;
+                    }
+                }
+            }
+
+            if (!found) {
+                var thetype = string.Join("::", n);
+                throw new Exception("Type {thetype} not found.");
+            }
+        }
+    }
+
     protected ModuleDefinition read_module(string path, bool readOnly) {
         var resolver = new DefaultAssemblyResolver();
         resolver.AddSearchDirectory(Path.GetDirectoryName(path));
@@ -69,16 +105,13 @@ class FixFileStreams : Command {
     private MethodReference betterFileStream;
 
     public FixFileStreams(FixFileStreamsCmd options) : base(options) {
-        var filtered = this.module.Types
-            .Where(p => options.typesToPatch.Contains(p.Name));
-
         this.betterFileStream = this.find_method_ref(
             "System.Void System.IO.FileStream::.ctor" +
             "(System.String,System.IO.FileMode,System.IO.FileAccess)"
         );
 
-        foreach (var toPatch in filtered)
-            patch_type(toPatch);
+        foreach (var toPatch in this.getm(options.typesToPatch))
+            patch_method(toPatch);
 
         this.save();
     }
@@ -97,11 +130,6 @@ class FixFileStreams : Command {
             il.Replace(i, il.Create(OpCodes.Newobj, this.betterFileStream));
         }
     }
-
-    private void patch_type(TypeDefinition td) {
-        foreach (var nested in td.NestedTypes) patch_type(nested);
-        foreach (MethodDefinition md in td.Methods) patch_method(md);
-    }
 }
 
 class ReplaceCall : Command {
@@ -117,12 +145,10 @@ class ReplaceCall : Command {
         this.search = options.replaceMethod;
         this.replace = this.find_method_ref(options.replacementMethod);
 
-        var filtered = this.module.Types
-            .Where(p => options.typesToPatch.Contains(p.Name));
-
         this.patch_done = false;
-        foreach (var toPatch in filtered)
-            patch_type(toPatch);
+
+        foreach (var toPatch in this.getm(options.typesToPatch))
+            patch_method(toPatch);
 
         if (!this.patch_done) {
             var types = string.Join(", ", options.typesToPatch);
@@ -151,11 +177,6 @@ class ReplaceCall : Command {
             this.patch_done = true;
         }
     }
-
-    private void patch_type(TypeDefinition td) {
-        foreach (var nested in td.NestedTypes) patch_type(nested);
-        foreach (MethodDefinition md in td.Methods) patch_method(md);
-    }
 }
 
 public class patcher {
diff --git a/pkgs/games/build-support/monogame-patcher/src/test.sh b/pkgs/games/build-support/monogame-patcher/src/test.sh
index b7380f27..b03fa6cb 100644
--- a/pkgs/games/build-support/monogame-patcher/src/test.sh
+++ b/pkgs/games/build-support/monogame-patcher/src/test.sh
@@ -18,7 +18,7 @@ using System.IO;
 
 public class b {
     public static string replacement(string bar) {
-        if (bar == "nope")
+        if (bar == "nope" || bar == "yikes")
             return "nope";
         Console.WriteLine("bar called: " + bar);
         return "bar";
@@ -49,15 +49,20 @@ EOF
 
 cat > "test1.cs" <<EOF
 class test1 {
+    public static void unrelated() {
+        b.replacement("yikes");
+    }
+
     public static void Main() {
         a.replaceMe("xxx");
         b.replacement("nope");
+        test1.unrelated();
     }
 }
 EOF
 
 cat > "test2.cs" <<EOF
-class test1 {
+class test2 {
     public static void Main() {
         b.wrongFileStreamUse();
     }
@@ -87,7 +92,7 @@ test "$(mono subdir/test1.exe)" = "bar called: xxx"
 "$out/bin/monogame-patcher" replace-call -i subdir/test1.exe -a subdir/c.dll \
     "System.String b::replacement(System.String)" \
     "System.String c::anotherReplacement(System.String)" \
-    test1
+    test1::Main
 
 test "$(mono subdir/test1.exe)" = "foobar called: xxx"