From 1838842bbc2db2d1049c193b8650bd101ba4858f Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 19 May 2020 20:57:50 -0400 Subject: rewrite assembly rewriting, merge Harmony rewriters (#711) This reduces duplication, decouples it from the assembly loader, and makes it more flexible to handle Harmony rewriting. --- .../Rewriters/FieldToPropertyRewriter.cs | 42 ++++++++++++---------- 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'src/SMAPI/Framework/ModLoading/Rewriters/FieldToPropertyRewriter.cs') diff --git a/src/SMAPI/Framework/ModLoading/Rewriters/FieldToPropertyRewriter.cs b/src/SMAPI/Framework/ModLoading/Rewriters/FieldToPropertyRewriter.cs index a43c5e9a..c3b5854e 100644 --- a/src/SMAPI/Framework/ModLoading/Rewriters/FieldToPropertyRewriter.cs +++ b/src/SMAPI/Framework/ModLoading/Rewriters/FieldToPropertyRewriter.cs @@ -1,21 +1,24 @@ using System; using Mono.Cecil; using Mono.Cecil.Cil; -using StardewModdingAPI.Framework.ModLoading.Finders; +using StardewModdingAPI.Framework.ModLoading.Framework; namespace StardewModdingAPI.Framework.ModLoading.Rewriters { /// Rewrites field references into property references. - internal class FieldToPropertyRewriter : FieldFinder + internal class FieldToPropertyRewriter : BaseInstructionHandler { /********* ** Fields *********/ - /// The type whose field to which references should be rewritten. + /// The type containing the field to which references should be rewritten. private readonly Type Type; - /// The property name. - private readonly string PropertyName; + /// The field name to which references should be rewritten. + private readonly string FromFieldName; + + /// The new property name. + private readonly string ToPropertyName; /********* @@ -26,10 +29,11 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters /// The field name to rewrite. /// The property name (if different). public FieldToPropertyRewriter(Type type, string fieldName, string propertyName) - : base(type.FullName, fieldName, InstructionHandleResult.None) + : base(defaultPhrase: $"{type.FullName}.{fieldName} field") { this.Type = type; - this.PropertyName = propertyName; + this.FromFieldName = fieldName; + this.ToPropertyName = propertyName; } /// Construct an instance. @@ -38,22 +42,24 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters public FieldToPropertyRewriter(Type type, string fieldName) : this(type, fieldName, fieldName) { } - /// Perform the predefined logic for an instruction if applicable. + /// Rewrite a CIL instruction reference if needed. /// The assembly module containing the instruction. /// The CIL processor. - /// The instruction to handle. - /// Metadata for mapping assemblies to the current platform. - /// Whether the mod was compiled on a different platform. - public override InstructionHandleResult Handle(ModuleDefinition module, ILProcessor cil, Instruction instruction, PlatformAssemblyMap assemblyMap, bool platformChanged) + /// The CIL instruction to handle. + /// Replaces the CIL instruction with a new one. + /// Returns whether the instruction was changed. + public override bool Handle(ModuleDefinition module, ILProcessor cil, Instruction instruction, Action replaceWith) { - if (!this.IsMatch(instruction)) - return InstructionHandleResult.None; + // get field ref + FieldReference fieldRef = RewriteHelper.AsFieldReference(instruction); + if (!RewriteHelper.IsFieldReferenceTo(fieldRef, this.Type.FullName, this.FromFieldName)) + return false; + // replace with property string methodPrefix = instruction.OpCode == OpCodes.Ldsfld || instruction.OpCode == OpCodes.Ldfld ? "get" : "set"; - MethodReference propertyRef = module.ImportReference(this.Type.GetMethod($"{methodPrefix}_{this.PropertyName}")); - cil.Replace(instruction, cil.Create(OpCodes.Call, propertyRef)); - - return InstructionHandleResult.Rewritten; + MethodReference propertyRef = module.ImportReference(this.Type.GetMethod($"{methodPrefix}_{this.ToPropertyName}")); + replaceWith(cil.Create(OpCodes.Call, propertyRef)); + return this.MarkRewritten(); } } } -- cgit