summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Finders/EventFinder.cs15
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Finders/FieldFinder.cs23
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Finders/MethodFinder.cs15
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Framework/BaseFieldFinder.cs46
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Framework/BaseFieldRewriter.cs35
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Framework/BaseMethodFinder.cs74
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Framework/BaseMethodRewriter.cs35
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Framework/RewriteHelper.cs41
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/RewriteHelper.cs94
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Rewriters/FieldReplaceRewriter.cs37
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Rewriters/FieldToPropertyRewriter.cs31
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/Rewriters/MethodParentRewriter.cs24
-rw-r--r--src/StardewModdingAPI.AssemblyRewriters/StardewModdingAPI.AssemblyRewriters.csproj6
-rw-r--r--src/StardewModdingAPI/Constants.cs2
14 files changed, 146 insertions, 332 deletions
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Finders/EventFinder.cs b/src/StardewModdingAPI.AssemblyRewriters/Finders/EventFinder.cs
index 359ca63e..9d0184c6 100644
--- a/src/StardewModdingAPI.AssemblyRewriters/Finders/EventFinder.cs
+++ b/src/StardewModdingAPI.AssemblyRewriters/Finders/EventFinder.cs
@@ -1,11 +1,10 @@
using Mono.Cecil;
using Mono.Cecil.Cil;
-using StardewModdingAPI.AssemblyRewriters.Framework;
namespace StardewModdingAPI.AssemblyRewriters.Finders
{
/// <summary>Finds CIL instructions that reference a given event.</summary>
- public sealed class EventFinder : BaseMethodFinder
+ public sealed class EventFinder : IInstructionFinder
{
/*********
** Properties
@@ -21,7 +20,7 @@ namespace StardewModdingAPI.AssemblyRewriters.Finders
** Accessors
*********/
/// <summary>A brief noun phrase indicating what the instruction finder matches.</summary>
- public override string NounPhrase { get; }
+ public string NounPhrase { get; }
/*********
@@ -41,13 +40,15 @@ namespace StardewModdingAPI.AssemblyRewriters.Finders
/*********
** Protected methods
*********/
- /// <summary>Get whether a method reference should be rewritten.</summary>
+ /// <summary>Get whether a CIL instruction matches.</summary>
/// <param name="instruction">The IL instruction.</param>
- /// <param name="methodRef">The method reference.</param>
/// <param name="platformChanged">Whether the mod was compiled on a different platform.</param>
- protected override bool IsMatch(Instruction instruction, MethodReference methodRef, bool platformChanged)
+ public bool IsMatch(Instruction instruction, bool platformChanged)
{
- return methodRef.DeclaringType.FullName == this.FullTypeName
+ MethodReference methodRef = RewriteHelper.AsMethodReference(instruction);
+ return
+ methodRef != null
+ && methodRef.DeclaringType.FullName == this.FullTypeName
&& (methodRef.Name == "add_" + this.EventName || methodRef.Name == "remove_" + this.EventName);
}
}
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Finders/FieldFinder.cs b/src/StardewModdingAPI.AssemblyRewriters/Finders/FieldFinder.cs
index 516641f2..068119b8 100644
--- a/src/StardewModdingAPI.AssemblyRewriters/Finders/FieldFinder.cs
+++ b/src/StardewModdingAPI.AssemblyRewriters/Finders/FieldFinder.cs
@@ -1,11 +1,10 @@
using Mono.Cecil;
using Mono.Cecil.Cil;
-using StardewModdingAPI.AssemblyRewriters.Framework;
namespace StardewModdingAPI.AssemblyRewriters.Finders
{
/// <summary>Finds CIL instructions that reference a given field.</summary>
- public sealed class FieldFinder : BaseFieldFinder
+ public class FieldFinder : IInstructionFinder
{
/*********
** Properties
@@ -16,15 +15,12 @@ namespace StardewModdingAPI.AssemblyRewriters.Finders
/// <summary>The field name for which to find references.</summary>
private readonly string FieldName;
- /// <summary>Whether the field to match is static.</summary>
- private readonly bool IsStatic;
-
/*********
** Accessors
*********/
/// <summary>A brief noun phrase indicating what the instruction finder matches.</summary>
- public override string NounPhrase { get; }
+ public string NounPhrase { get; }
/*********
@@ -33,27 +29,26 @@ namespace StardewModdingAPI.AssemblyRewriters.Finders
/// <summary>Construct an instance.</summary>
/// <param name="fullTypeName">The full type name for which to find references.</param>
/// <param name="fieldName">The field name for which to find references.</param>
- /// <param name="isStatic">Whether the field to match is static.</param>
- public FieldFinder(string fullTypeName, string fieldName, bool isStatic)
+ /// <param name="nounPhrase">A brief noun phrase indicating what the instruction finder matches (or <c>null</c> to generate one).</param>
+ public FieldFinder(string fullTypeName, string fieldName, string nounPhrase = null)
{
this.FullTypeName = fullTypeName;
this.FieldName = fieldName;
- this.IsStatic = isStatic;
- this.NounPhrase = $"obsolete {fullTypeName}.{fieldName} field";
+ this.NounPhrase = nounPhrase ?? $"{fullTypeName}.{fieldName} field";
}
/*********
** Protected methods
*********/
- /// <summary>Get whether a field reference should be rewritten.</summary>
+ /// <summary>Get whether a CIL instruction matches.</summary>
/// <param name="instruction">The IL instruction.</param>
- /// <param name="fieldRef">The field reference.</param>
/// <param name="platformChanged">Whether the mod was compiled on a different platform.</param>
- protected override bool IsMatch(Instruction instruction, FieldReference fieldRef, bool platformChanged)
+ public bool IsMatch(Instruction instruction, bool platformChanged)
{
+ FieldReference fieldRef = RewriteHelper.AsFieldReference(instruction);
return
- this.IsStaticField(instruction) == this.IsStatic
+ fieldRef != null
&& fieldRef.DeclaringType.FullName == this.FullTypeName
&& fieldRef.Name == this.FieldName;
}
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Finders/MethodFinder.cs b/src/StardewModdingAPI.AssemblyRewriters/Finders/MethodFinder.cs
index 6c210d68..bea549ee 100644
--- a/src/StardewModdingAPI.AssemblyRewriters/Finders/MethodFinder.cs
+++ b/src/StardewModdingAPI.AssemblyRewriters/Finders/MethodFinder.cs
@@ -1,11 +1,10 @@
using Mono.Cecil;
using Mono.Cecil.Cil;
-using StardewModdingAPI.AssemblyRewriters.Framework;
namespace StardewModdingAPI.AssemblyRewriters.Finders
{
/// <summary>Finds CIL instructions that reference a given method.</summary>
- public sealed class MethodFinder : BaseMethodFinder
+ public class MethodFinder : IInstructionFinder
{
/*********
** Properties
@@ -21,7 +20,7 @@ namespace StardewModdingAPI.AssemblyRewriters.Finders
** Accessors
*********/
/// <summary>A brief noun phrase indicating what the instruction finder matches.</summary>
- public override string NounPhrase { get; }
+ public string NounPhrase { get; }
/*********
@@ -41,13 +40,15 @@ namespace StardewModdingAPI.AssemblyRewriters.Finders
/*********
** Protected methods
*********/
- /// <summary>Get whether a method reference should be rewritten.</summary>
+ /// <summary>Get whether a CIL instruction matches.</summary>
/// <param name="instruction">The IL instruction.</param>
- /// <param name="methodRef">The method reference.</param>
/// <param name="platformChanged">Whether the mod was compiled on a different platform.</param>
- protected override bool IsMatch(Instruction instruction, MethodReference methodRef, bool platformChanged)
+ public bool IsMatch(Instruction instruction, bool platformChanged)
{
- return methodRef.DeclaringType.FullName == this.FullTypeName
+ MethodReference methodRef = RewriteHelper.AsMethodReference(instruction);
+ return
+ methodRef != null
+ && methodRef.DeclaringType.FullName == this.FullTypeName
&& methodRef.Name == this.MethodName;
}
}
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseFieldFinder.cs b/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseFieldFinder.cs
deleted file mode 100644
index ac2facec..00000000
--- a/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseFieldFinder.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-using Mono.Cecil;
-using Mono.Cecil.Cil;
-
-namespace StardewModdingAPI.AssemblyRewriters.Framework
-{
- /// <summary>Base class for a field finder.</summary>
- public abstract class BaseFieldFinder : IInstructionFinder
- {
- /*********
- ** Accessors
- *********/
- /// <summary>A brief noun phrase indicating what the instruction finder matches.</summary>
- public abstract string NounPhrase { get; }
-
-
- /*********
- ** Public methods
- *********/
- /// <summary>Get whether a CIL instruction matches.</summary>
- /// <param name="instruction">The IL instruction.</param>
- /// <param name="platformChanged">Whether the mod was compiled on a different platform.</param>
- public bool IsMatch(Instruction instruction, bool platformChanged)
- {
- if (instruction.OpCode != OpCodes.Ldfld && instruction.OpCode != OpCodes.Ldsfld && instruction.OpCode != OpCodes.Stfld && instruction.OpCode != OpCodes.Stsfld)
- return false; // not a field reference
- return this.IsMatch(instruction, (FieldReference)instruction.Operand, platformChanged);
- }
-
-
- /*********
- ** Protected methods
- *********/
- /// <summary>Get whether a field reference should be rewritten.</summary>
- /// <param name="instruction">The IL instruction.</param>
- /// <param name="fieldRef">The field reference.</param>
- /// <param name="platformChanged">Whether the mod was compiled on a different platform.</param>
- protected abstract bool IsMatch(Instruction instruction, FieldReference fieldRef, bool platformChanged);
-
- /// <summary>Whether an instruction is a static field reference.</summary>
- /// <param name="instruction">The IL instruction.</param>
- protected bool IsStaticField(Instruction instruction)
- {
- return instruction.OpCode == OpCodes.Ldsfld || instruction.OpCode == OpCodes.Stsfld;
- }
- }
-}
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseFieldRewriter.cs b/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseFieldRewriter.cs
deleted file mode 100644
index b2c25587..00000000
--- a/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseFieldRewriter.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using Mono.Cecil;
-using Mono.Cecil.Cil;
-
-namespace StardewModdingAPI.AssemblyRewriters.Framework
-{
- /// <summary>Base class for a field rewriter.</summary>
- public abstract class BaseFieldRewriter : BaseFieldFinder, IInstructionRewriter
- {
- /*********
- ** Public methods
- *********/
- /// <summary>Rewrite a CIL instruction for compatibility.</summary>
- /// <param name="module">The module being rewritten.</param>
- /// <param name="cil">The CIL rewriter.</param>
- /// <param name="instruction">The instruction to rewrite.</param>
- /// <param name="assemblyMap">Metadata for mapping assemblies to the current platform.</param>
- public void Rewrite(ModuleDefinition module, ILProcessor cil, Instruction instruction, PlatformAssemblyMap assemblyMap)
- {
- FieldReference fieldRef = (FieldReference)instruction.Operand;
- this.Rewrite(module, cil, instruction, fieldRef, assemblyMap);
- }
-
-
- /*********
- ** Protected methods
- *********/
- /// <summary>Rewrite a method for compatibility.</summary>
- /// <param name="module">The module being rewritten.</param>
- /// <param name="cil">The CIL rewriter.</param>
- /// <param name="instruction">The instruction which references the field.</param>
- /// <param name="fieldRef">The field reference invoked by the <paramref name="instruction"/>.</param>
- /// <param name="assemblyMap">Metadata for mapping assemblies to the current platform.</param>
- protected abstract void Rewrite(ModuleDefinition module, ILProcessor cil, Instruction instruction, FieldReference fieldRef, PlatformAssemblyMap assemblyMap);
- }
-}
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseMethodFinder.cs b/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseMethodFinder.cs
deleted file mode 100644
index bb71a9d7..00000000
--- a/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseMethodFinder.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-using System;
-using System.Linq;
-using System.Reflection;
-using Mono.Cecil;
-using Mono.Cecil.Cil;
-
-namespace StardewModdingAPI.AssemblyRewriters.Framework
-{
- /// <summary>Base class for a method finder.</summary>
- public abstract class BaseMethodFinder : IInstructionFinder
- {
- /*********
- ** Accessors
- *********/
- /// <summary>A brief noun phrase indicating what the instruction finder matches.</summary>
- public abstract string NounPhrase { get; }
-
-
- /*********
- ** Public methods
- *********/
- /// <summary>Get whether a CIL instruction matches.</summary>
- /// <param name="instruction">The IL instruction.</param>
- /// <param name="platformChanged">Whether the mod was compiled on a different platform.</param>
- 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
- *********/
- /// <summary>Get whether a method reference should be rewritten.</summary>
- /// <param name="instruction">The IL instruction.</param>
- /// <param name="methodRef">The method reference.</param>
- /// <param name="platformChanged">Whether the mod was compiled on a different platform.</param>
- protected abstract bool IsMatch(Instruction instruction, MethodReference methodRef, bool platformChanged);
-
- /// <summary>Get whether a method definition matches the signature expected by a method reference.</summary>
- /// <param name="definition">The method definition.</param>
- /// <param name="reference">The method reference.</param>
- 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;
- }
-
- /// <summary>Get whether a type has a method whose signature matches the one expected by a method reference.</summary>
- /// <param name="type">The type to check.</param>
- /// <param name="reference">The method reference.</param>
- protected bool HasMatchingSignature(Type type, MethodReference reference)
- {
- return type
- .GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public)
- .Any(method => this.HasMatchingSignature(method, reference));
- }
- }
-}
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseMethodRewriter.cs b/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseMethodRewriter.cs
deleted file mode 100644
index 6af1a0e1..00000000
--- a/src/StardewModdingAPI.AssemblyRewriters/Framework/BaseMethodRewriter.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using Mono.Cecil;
-using Mono.Cecil.Cil;
-
-namespace StardewModdingAPI.AssemblyRewriters.Framework
-{
- /// <summary>Base class for a method rewriter.</summary>
- public abstract class BaseMethodRewriter : BaseMethodFinder, IInstructionRewriter
- {
- /*********
- ** Public methods
- *********/
- /// <summary>Rewrite a CIL instruction for compatibility.</summary>
- /// <param name="module">The module being rewritten.</param>
- /// <param name="cil">The CIL rewriter.</param>
- /// <param name="instruction">The instruction to rewrite.</param>
- /// <param name="assemblyMap">Metadata for mapping assemblies to the current platform.</param>
- public void Rewrite(ModuleDefinition module, ILProcessor cil, Instruction instruction, PlatformAssemblyMap assemblyMap)
- {
- MethodReference methodRef = (MethodReference)instruction.Operand;
- this.Rewrite(module, cil, instruction, methodRef, assemblyMap);
- }
-
-
- /*********
- ** Protected methods
- *********/
- /// <summary>Rewrite a method for compatibility.</summary>
- /// <param name="module">The module being rewritten.</param>
- /// <param name="cil">The CIL rewriter.</param>
- /// <param name="instruction">The instruction which calls the method.</param>
- /// <param name="methodRef">The method reference invoked by the <paramref name="instruction"/>.</param>
- /// <param name="assemblyMap">Metadata for mapping assemblies to the current platform.</param>
- protected abstract void Rewrite(ModuleDefinition module, ILProcessor cil, Instruction instruction, MethodReference methodRef, PlatformAssemblyMap assemblyMap);
- }
-}
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Framework/RewriteHelper.cs b/src/StardewModdingAPI.AssemblyRewriters/Framework/RewriteHelper.cs
deleted file mode 100644
index 0307053f..00000000
--- a/src/StardewModdingAPI.AssemblyRewriters/Framework/RewriteHelper.cs
+++ /dev/null
@@ -1,41 +0,0 @@
-using System;
-using Mono.Cecil;
-
-namespace StardewModdingAPI.AssemblyRewriters.Framework
-{
- /// <summary>Provides helper methods for field rewriters.</summary>
- internal static class RewriteHelper
- {
- /*********
- ** Public methods
- *********/
- /// <summary>Get whether a type matches a type reference.</summary>
- /// <param name="type">The defined type.</param>
- /// <param name="reference">The type reference.</param>
- public static bool IsMatchingType(Type type, TypeReference reference)
- {
- // same namespace & name
- if (type.Namespace != reference.Namespace || type.Name != reference.Name)
- return false;
-
- // same generic parameters
- if (type.IsGenericType)
- {
- if (!reference.IsGenericInstance)
- return false;
-
- Type[] defGenerics = type.GetGenericArguments();
- TypeReference[] refGenerics = ((GenericInstanceType)reference).GenericArguments.ToArray();
- if (defGenerics.Length != refGenerics.Length)
- return false;
- for (int i = 0; i < defGenerics.Length; i++)
- {
- if (!RewriteHelper.IsMatchingType(defGenerics[i], refGenerics[i]))
- return false;
- }
- }
-
- return true;
- }
- }
-}
diff --git a/src/StardewModdingAPI.AssemblyRewriters/RewriteHelper.cs b/src/StardewModdingAPI.AssemblyRewriters/RewriteHelper.cs
new file mode 100644
index 00000000..cfb330dd
--- /dev/null
+++ b/src/StardewModdingAPI.AssemblyRewriters/RewriteHelper.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Linq;
+using System.Reflection;
+using Mono.Cecil;
+using Mono.Cecil.Cil;
+
+namespace StardewModdingAPI.AssemblyRewriters
+{
+ /// <summary>Provides helper methods for field rewriters.</summary>
+ internal static class RewriteHelper
+ {
+ /*********
+ ** Public methods
+ *********/
+ /// <summary>Get the field reference from an instruction if it matches.</summary>
+ /// <param name="instruction">The IL instruction.</param>
+ public static FieldReference AsFieldReference(Instruction instruction)
+ {
+ return instruction.OpCode == OpCodes.Ldfld || instruction.OpCode == OpCodes.Ldsfld || instruction.OpCode == OpCodes.Stfld || instruction.OpCode == OpCodes.Stsfld
+ ? (FieldReference)instruction.Operand
+ : null;
+ }
+
+ /// <summary>Get the method reference from an instruction if it matches.</summary>
+ /// <param name="instruction">The IL instruction.</param>
+ public static MethodReference AsMethodReference(Instruction instruction)
+ {
+ return instruction.OpCode == OpCodes.Call || instruction.OpCode == OpCodes.Callvirt
+ ? (MethodReference)instruction.Operand
+ : null;
+ }
+
+ /// <summary>Get whether a type matches a type reference.</summary>
+ /// <param name="type">The defined type.</param>
+ /// <param name="reference">The type reference.</param>
+ public static bool IsSameType(Type type, TypeReference reference)
+ {
+ // same namespace & name
+ if (type.Namespace != reference.Namespace || type.Name != reference.Name)
+ return false;
+
+ // same generic parameters
+ if (type.IsGenericType)
+ {
+ if (!reference.IsGenericInstance)
+ return false;
+
+ Type[] defGenerics = type.GetGenericArguments();
+ TypeReference[] refGenerics = ((GenericInstanceType)reference).GenericArguments.ToArray();
+ if (defGenerics.Length != refGenerics.Length)
+ return false;
+ for (int i = 0; i < defGenerics.Length; i++)
+ {
+ if (!RewriteHelper.IsSameType(defGenerics[i], refGenerics[i]))
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /// <summary>Get whether a method definition matches the signature expected by a method reference.</summary>
+ /// <param name="definition">The method definition.</param>
+ /// <param name="reference">The method reference.</param>
+ public static 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.IsSameType(definitionParameters[i].ParameterType, referenceParameters[i].ParameterType))
+ return false;
+ }
+ return true;
+ }
+
+ /// <summary>Get whether a type has a method whose signature matches the one expected by a method reference.</summary>
+ /// <param name="type">The type to check.</param>
+ /// <param name="reference">The method reference.</param>
+ public static bool HasMatchingSignature(Type type, MethodReference reference)
+ {
+ return type
+ .GetMethods(BindingFlags.Instance | BindingFlags.DeclaredOnly | BindingFlags.Public)
+ .Any(method => RewriteHelper.HasMatchingSignature(method, reference));
+ }
+ }
+}
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/FieldReplaceRewriter.cs b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/FieldReplaceRewriter.cs
index 31f9a40f..a715e07b 100644
--- a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/FieldReplaceRewriter.cs
+++ b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/FieldReplaceRewriter.cs
@@ -2,12 +2,12 @@ using System;
using System.Reflection;
using Mono.Cecil;
using Mono.Cecil.Cil;
-using StardewModdingAPI.AssemblyRewriters.Framework;
+using StardewModdingAPI.AssemblyRewriters.Finders;
namespace StardewModdingAPI.AssemblyRewriters.Rewriters
{
/// <summary>Rewrites references to one field with another.</summary>
- public class FieldReplaceRewriter : BaseFieldRewriter
+ public class FieldReplaceRewriter : FieldFinder, IInstructionRewriter
{
/*********
** Properties
@@ -15,21 +15,11 @@ namespace StardewModdingAPI.AssemblyRewriters.Rewriters
/// <summary>The type whose field to which references should be rewritten.</summary>
private readonly Type Type;
- /// <summary>The field name to rewrite.</summary>
- private readonly string FromFieldName;
-
/// <summary>The new field name to reference.</summary>
private readonly string ToFieldName;
/*********
- ** Accessors
- *********/
- /// <summary>A brief noun phrase indicating what the instruction finder matches.</summary>
- public override string NounPhrase { get; }
-
-
- /*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
@@ -38,38 +28,25 @@ namespace StardewModdingAPI.AssemblyRewriters.Rewriters
/// <param name="toFieldName">The new field name to reference.</param>
/// <param name="nounPhrase">A brief noun phrase indicating what the instruction finder matches (or <c>null</c> to generate one).</param>
public FieldReplaceRewriter(Type type, string fromFieldName, string toFieldName, string nounPhrase = null)
+ : base(type.FullName, fromFieldName, nounPhrase)
{
this.Type = type;
- this.FromFieldName = fromFieldName;
this.ToFieldName = toFieldName;
- this.NounPhrase = nounPhrase ?? $"{type.Name}.{fromFieldName} field";
}
/*********
** Protected methods
*********/
- /// <summary>Get whether a field reference should be rewritten.</summary>
- /// <param name="instruction">The IL instruction.</param>
- /// <param name="fieldRef">The field reference.</param>
- /// <param name="platformChanged">Whether the mod was compiled on a different platform.</param>
- protected override bool IsMatch(Instruction instruction, FieldReference fieldRef, bool platformChanged)
- {
- return
- fieldRef.DeclaringType.FullName == this.Type.FullName
- && fieldRef.Name == this.FromFieldName;
- }
-
- /// <summary>Rewrite a method for compatibility.</summary>
+ /// <summary>Rewrite a CIL instruction for compatibility.</summary>
/// <param name="module">The module being rewritten.</param>
/// <param name="cil">The CIL rewriter.</param>
- /// <param name="instruction">The instruction which references the field.</param>
- /// <param name="fieldRef">The field reference invoked by the <paramref name="instruction"/>.</param>
+ /// <param name="instruction">The instruction to rewrite.</param>
/// <param name="assemblyMap">Metadata for mapping assemblies to the current platform.</param>
- protected override void Rewrite(ModuleDefinition module, ILProcessor cil, Instruction instruction, FieldReference fieldRef, PlatformAssemblyMap assemblyMap)
+ public void Rewrite(ModuleDefinition module, ILProcessor cil, Instruction instruction, PlatformAssemblyMap assemblyMap)
{
FieldInfo field = this.Type.GetField(this.ToFieldName);
- if(field == null)
+ if (field == null)
throw new InvalidOperationException($"The {this.Type.FullName} class doesn't have a {this.ToFieldName} field.");
FieldReference newRef = module.Import(field);
cil.Replace(instruction, cil.Create(instruction.OpCode, newRef));
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/FieldToPropertyRewriter.cs b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/FieldToPropertyRewriter.cs
index caf0a16c..62e24559 100644
--- a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/FieldToPropertyRewriter.cs
+++ b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/FieldToPropertyRewriter.cs
@@ -1,12 +1,12 @@
using System;
using Mono.Cecil;
using Mono.Cecil.Cil;
-using StardewModdingAPI.AssemblyRewriters.Framework;
+using StardewModdingAPI.AssemblyRewriters.Finders;
namespace StardewModdingAPI.AssemblyRewriters.Rewriters
{
/// <summary>Rewrites field references into property references.</summary>
- public class FieldToPropertyRewriter : BaseFieldRewriter
+ public class FieldToPropertyRewriter : FieldFinder, IInstructionRewriter
{
/*********
** Properties
@@ -19,13 +19,6 @@ namespace StardewModdingAPI.AssemblyRewriters.Rewriters
/*********
- ** Accessors
- *********/
- /// <summary>A brief noun phrase indicating what the instruction finder matches.</summary>
- public override string NounPhrase { get; }
-
-
- /*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
@@ -33,34 +26,22 @@ namespace StardewModdingAPI.AssemblyRewriters.Rewriters
/// <param name="fieldName">The field name to rewrite.</param>
/// <param name="nounPhrase">A brief noun phrase indicating what the instruction finder matches (or <c>null</c> to generate one).</param>
public FieldToPropertyRewriter(Type type, string fieldName, string nounPhrase = null)
+ : base(type.FullName, fieldName, nounPhrase)
{
this.Type = type;
this.FieldName = fieldName;
- this.NounPhrase = nounPhrase ?? $"{type.Name}.{fieldName} field";
}
/*********
** Protected methods
*********/
- /// <summary>Get whether a field reference should be rewritten.</summary>
- /// <param name="instruction">The IL instruction.</param>
- /// <param name="fieldRef">The field reference.</param>
- /// <param name="platformChanged">Whether the mod was compiled on a different platform.</param>
- protected override bool IsMatch(Instruction instruction, FieldReference fieldRef, bool platformChanged)
- {
- return
- fieldRef.DeclaringType.FullName == this.Type.FullName
- && fieldRef.Name == this.FieldName;
- }
-
- /// <summary>Rewrite a method for compatibility.</summary>
+ /// <summary>Rewrite a CIL instruction for compatibility.</summary>
/// <param name="module">The module being rewritten.</param>
/// <param name="cil">The CIL rewriter.</param>
- /// <param name="instruction">The instruction which references the field.</param>
- /// <param name="fieldRef">The field reference invoked by the <paramref name="instruction"/>.</param>
+ /// <param name="instruction">The instruction to rewrite.</param>
/// <param name="assemblyMap">Metadata for mapping assemblies to the current platform.</param>
- protected override void Rewrite(ModuleDefinition module, ILProcessor cil, Instruction instruction, FieldReference fieldRef, PlatformAssemblyMap assemblyMap)
+ public void Rewrite(ModuleDefinition module, ILProcessor cil, Instruction instruction, PlatformAssemblyMap assemblyMap)
{
string methodPrefix = instruction.OpCode == OpCodes.Ldsfld || instruction.OpCode == OpCodes.Ldfld ? "get" : "set";
MethodReference propertyRef = module.Import(this.Type.GetMethod($"{methodPrefix}_{this.FieldName}"));
diff --git a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/MethodParentRewriter.cs b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/MethodParentRewriter.cs
index 9c19f473..9b895056 100644
--- a/src/StardewModdingAPI.AssemblyRewriters/Rewriters/MethodParentRewriter.cs
+++ b/src/StardewModdingAPI.AssemblyRewriters/Rewriters/MethodParentRewriter.cs
@@ -1,12 +1,11 @@
using System;
using Mono.Cecil;
using Mono.Cecil.Cil;
-using StardewModdingAPI.AssemblyRewriters.Framework;
namespace StardewModdingAPI.AssemblyRewriters.Rewriters
{
/// <summary>Rewrites method references from one parent type to another if the signatures match.</summary>
- public class MethodParentRewriter : BaseMethodRewriter
+ public class MethodParentRewriter : IInstructionRewriter
{
/*********
** Properties
@@ -25,7 +24,7 @@ namespace StardewModdingAPI.AssemblyRewriters.Rewriters
** Accessors
*********/
/// <summary>A brief noun phrase indicating what the instruction finder matches.</summary>
- public override string NounPhrase { get; }
+ public string NounPhrase { get; }
/*********
@@ -48,26 +47,27 @@ namespace StardewModdingAPI.AssemblyRewriters.Rewriters
/*********
** Protected methods
*********/
- /// <summary>Get whether a method reference should be rewritten.</summary>
+ /// <summary>Get whether a CIL instruction matches.</summary>
/// <param name="instruction">The IL instruction.</param>
- /// <param name="methodRef">The method reference.</param>
/// <param name="platformChanged">Whether the mod was compiled on a different platform.</param>
- protected override bool IsMatch(Instruction instruction, MethodReference methodRef, bool platformChanged)
+ public bool IsMatch(Instruction instruction, bool platformChanged)
{
+ MethodReference methodRef = RewriteHelper.AsMethodReference(instruction);
return
- (!this.OnlyIfPlatformChanged || platformChanged)
+ methodRef != null
+ && (platformChanged || !this.OnlyIfPlatformChanged)
&& methodRef.DeclaringType.FullName == this.FromType.FullName
- && this.HasMatchingSignature(this.ToType, methodRef);
+ && RewriteHelper.HasMatchingSignature(this.ToType, methodRef);
}
- /// <summary>Rewrite a method for compatibility.</summary>
+ /// <summary>Rewrite a CIL instruction for compatibility.</summary>
/// <param name="module">The module being rewritten.</param>
/// <param name="cil">The CIL rewriter.</param>
- /// <param name="instruction">The instruction which calls the method.</param>
- /// <param name="methodRef">The method reference invoked by the <paramref name="instruction"/>.</param>
+ /// <param name="instruction">The instruction to rewrite.</param>
/// <param name="assemblyMap">Metadata for mapping assemblies to the current platform.</param>
- protected override void Rewrite(ModuleDefinition module, ILProcessor cil, Instruction instruction, MethodReference methodRef, PlatformAssemblyMap assemblyMap)
+ public void Rewrite(ModuleDefinition module, ILProcessor cil, Instruction instruction, PlatformAssemblyMap assemblyMap)
{
+ MethodReference methodRef = (MethodReference)instruction.Operand;
methodRef.DeclaringType = module.Import(this.ToType);
}
}
diff --git a/src/StardewModdingAPI.AssemblyRewriters/StardewModdingAPI.AssemblyRewriters.csproj b/src/StardewModdingAPI.AssemblyRewriters/StardewModdingAPI.AssemblyRewriters.csproj
index 0136c39b..09fd79ed 100644
--- a/src/StardewModdingAPI.AssemblyRewriters/StardewModdingAPI.AssemblyRewriters.csproj
+++ b/src/StardewModdingAPI.AssemblyRewriters/StardewModdingAPI.AssemblyRewriters.csproj
@@ -70,11 +70,7 @@
<Compile Include="Finders\FieldFinder.cs" />
<Compile Include="Finders\MethodFinder.cs" />
<Compile Include="Finders\TypeFinder.cs" />
- <Compile Include="Framework\BaseFieldFinder.cs" />
- <Compile Include="Framework\BaseFieldRewriter.cs" />
- <Compile Include="Framework\BaseMethodFinder.cs" />
- <Compile Include="Framework\BaseMethodRewriter.cs" />
- <Compile Include="Framework\RewriteHelper.cs" />
+ <Compile Include="RewriteHelper.cs" />
<Compile Include="IInstructionFinder.cs" />
<Compile Include="IInstructionRewriter.cs" />
<Compile Include="Platform.cs" />
diff --git a/src/StardewModdingAPI/Constants.cs b/src/StardewModdingAPI/Constants.cs
index 9a7fba84..52be6c05 100644
--- a/src/StardewModdingAPI/Constants.cs
+++ b/src/StardewModdingAPI/Constants.cs
@@ -143,7 +143,7 @@ namespace StardewModdingAPI
return new IInstructionFinder[]
{
// changes in Stardew Valley 1.2 (that don't have rewriters)
- new FieldFinder("StardewValley.Item", "set_Name", isStatic: false),
+ new FieldFinder("StardewValley.Item", "set_Name"),
// APIs removed in SMAPI 1.9
new TypeFinder("StardewModdingAPI.Advanced.ConfigFile"),