From 929dccb75a1405737975d76648e015a3e7c00177 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Sat, 7 Oct 2017 23:07:10 -0400 Subject: reorganise repo structure --- .../Framework/ModLoading/Finders/EventFinder.cs | 82 +++++++++++++ .../Framework/ModLoading/Finders/FieldFinder.cs | 82 +++++++++++++ .../Framework/ModLoading/Finders/MethodFinder.cs | 82 +++++++++++++ .../Framework/ModLoading/Finders/PropertyFinder.cs | 82 +++++++++++++ .../Framework/ModLoading/Finders/TypeFinder.cs | 133 +++++++++++++++++++++ 5 files changed, 461 insertions(+) create mode 100644 src/SMAPI/Framework/ModLoading/Finders/EventFinder.cs create mode 100644 src/SMAPI/Framework/ModLoading/Finders/FieldFinder.cs create mode 100644 src/SMAPI/Framework/ModLoading/Finders/MethodFinder.cs create mode 100644 src/SMAPI/Framework/ModLoading/Finders/PropertyFinder.cs create mode 100644 src/SMAPI/Framework/ModLoading/Finders/TypeFinder.cs (limited to 'src/SMAPI/Framework/ModLoading/Finders') diff --git a/src/SMAPI/Framework/ModLoading/Finders/EventFinder.cs b/src/SMAPI/Framework/ModLoading/Finders/EventFinder.cs new file mode 100644 index 00000000..e4beb7a9 --- /dev/null +++ b/src/SMAPI/Framework/ModLoading/Finders/EventFinder.cs @@ -0,0 +1,82 @@ +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace StardewModdingAPI.Framework.ModLoading.Finders +{ + /// Finds incompatible CIL instructions that reference a given event. + internal class EventFinder : IInstructionHandler + { + /********* + ** Properties + *********/ + /// The full type name for which to find references. + private readonly string FullTypeName; + + /// The event name for which to find references. + private readonly string EventName; + + /// The result to return for matching instructions. + private readonly InstructionHandleResult Result; + + + /********* + ** Accessors + *********/ + /// A brief noun phrase indicating what the instruction finder matches. + public string NounPhrase { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The full type name for which to find references. + /// The event name for which to find references. + /// The result to return for matching instructions. + public EventFinder(string fullTypeName, string eventName, InstructionHandleResult result) + { + this.FullTypeName = fullTypeName; + this.EventName = eventName; + this.Result = result; + this.NounPhrase = $"{fullTypeName}.{eventName} event"; + } + + /// Perform the predefined logic for a method if applicable. + /// The assembly module containing the instruction. + /// The method definition containing the instruction. + /// Metadata for mapping assemblies to the current platform. + /// Whether the mod was compiled on a different platform. + public virtual InstructionHandleResult Handle(ModuleDefinition module, MethodDefinition method, PlatformAssemblyMap assemblyMap, bool platformChanged) + { + return InstructionHandleResult.None; + } + + /// Perform the predefined logic for an instruction if applicable. + /// 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 virtual InstructionHandleResult Handle(ModuleDefinition module, ILProcessor cil, Instruction instruction, PlatformAssemblyMap assemblyMap, bool platformChanged) + { + return this.IsMatch(instruction) + ? this.Result + : InstructionHandleResult.None; + } + + + /********* + ** Protected methods + *********/ + /// Get whether a CIL instruction matches. + /// The IL instruction. + protected bool IsMatch(Instruction instruction) + { + 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/SMAPI/Framework/ModLoading/Finders/FieldFinder.cs b/src/SMAPI/Framework/ModLoading/Finders/FieldFinder.cs new file mode 100644 index 00000000..00805815 --- /dev/null +++ b/src/SMAPI/Framework/ModLoading/Finders/FieldFinder.cs @@ -0,0 +1,82 @@ +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace StardewModdingAPI.Framework.ModLoading.Finders +{ + /// Finds incompatible CIL instructions that reference a given field. + internal class FieldFinder : IInstructionHandler + { + /********* + ** Properties + *********/ + /// The full type name for which to find references. + private readonly string FullTypeName; + + /// The field name for which to find references. + private readonly string FieldName; + + /// The result to return for matching instructions. + private readonly InstructionHandleResult Result; + + + /********* + ** Accessors + *********/ + /// A brief noun phrase indicating what the instruction finder matches. + public string NounPhrase { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The full type name for which to find references. + /// The field name for which to find references. + /// The result to return for matching instructions. + public FieldFinder(string fullTypeName, string fieldName, InstructionHandleResult result) + { + this.FullTypeName = fullTypeName; + this.FieldName = fieldName; + this.Result = result; + this.NounPhrase = $"{fullTypeName}.{fieldName} field"; + } + + /// Perform the predefined logic for a method if applicable. + /// The assembly module containing the instruction. + /// The method definition containing the instruction. + /// Metadata for mapping assemblies to the current platform. + /// Whether the mod was compiled on a different platform. + public virtual InstructionHandleResult Handle(ModuleDefinition module, MethodDefinition method, PlatformAssemblyMap assemblyMap, bool platformChanged) + { + return InstructionHandleResult.None; + } + + /// Perform the predefined logic for an instruction if applicable. + /// 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 virtual InstructionHandleResult Handle(ModuleDefinition module, ILProcessor cil, Instruction instruction, PlatformAssemblyMap assemblyMap, bool platformChanged) + { + return this.IsMatch(instruction) + ? this.Result + : InstructionHandleResult.None; + } + + + /********* + ** Protected methods + *********/ + /// Get whether a CIL instruction matches. + /// The IL instruction. + protected bool IsMatch(Instruction instruction) + { + FieldReference fieldRef = RewriteHelper.AsFieldReference(instruction); + return + fieldRef != null + && fieldRef.DeclaringType.FullName == this.FullTypeName + && fieldRef.Name == this.FieldName; + } + } +} diff --git a/src/SMAPI/Framework/ModLoading/Finders/MethodFinder.cs b/src/SMAPI/Framework/ModLoading/Finders/MethodFinder.cs new file mode 100644 index 00000000..5358f181 --- /dev/null +++ b/src/SMAPI/Framework/ModLoading/Finders/MethodFinder.cs @@ -0,0 +1,82 @@ +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace StardewModdingAPI.Framework.ModLoading.Finders +{ + /// Finds incompatible CIL instructions that reference a given method. + internal class MethodFinder : IInstructionHandler + { + /********* + ** Properties + *********/ + /// The full type name for which to find references. + private readonly string FullTypeName; + + /// The method name for which to find references. + private readonly string MethodName; + + /// The result to return for matching instructions. + private readonly InstructionHandleResult Result; + + + /********* + ** Accessors + *********/ + /// A brief noun phrase indicating what the instruction finder matches. + public string NounPhrase { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The full type name for which to find references. + /// The method name for which to find references. + /// The result to return for matching instructions. + public MethodFinder(string fullTypeName, string methodName, InstructionHandleResult result) + { + this.FullTypeName = fullTypeName; + this.MethodName = methodName; + this.Result = result; + this.NounPhrase = $"{fullTypeName}.{methodName} method"; + } + + /// Perform the predefined logic for a method if applicable. + /// The assembly module containing the instruction. + /// The method definition containing the instruction. + /// Metadata for mapping assemblies to the current platform. + /// Whether the mod was compiled on a different platform. + public virtual InstructionHandleResult Handle(ModuleDefinition module, MethodDefinition method, PlatformAssemblyMap assemblyMap, bool platformChanged) + { + return InstructionHandleResult.None; + } + + /// Perform the predefined logic for an instruction if applicable. + /// 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 InstructionHandleResult Handle(ModuleDefinition module, ILProcessor cil, Instruction instruction, PlatformAssemblyMap assemblyMap, bool platformChanged) + { + return this.IsMatch(instruction) + ? this.Result + : InstructionHandleResult.None; + } + + + /********* + ** Protected methods + *********/ + /// Get whether a CIL instruction matches. + /// The IL instruction. + protected bool IsMatch(Instruction instruction) + { + MethodReference methodRef = RewriteHelper.AsMethodReference(instruction); + return + methodRef != null + && methodRef.DeclaringType.FullName == this.FullTypeName + && methodRef.Name == this.MethodName; + } + } +} diff --git a/src/SMAPI/Framework/ModLoading/Finders/PropertyFinder.cs b/src/SMAPI/Framework/ModLoading/Finders/PropertyFinder.cs new file mode 100644 index 00000000..e54c86cf --- /dev/null +++ b/src/SMAPI/Framework/ModLoading/Finders/PropertyFinder.cs @@ -0,0 +1,82 @@ +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace StardewModdingAPI.Framework.ModLoading.Finders +{ + /// Finds incompatible CIL instructions that reference a given property. + internal class PropertyFinder : IInstructionHandler + { + /********* + ** Properties + *********/ + /// The full type name for which to find references. + private readonly string FullTypeName; + + /// The property name for which to find references. + private readonly string PropertyName; + + /// The result to return for matching instructions. + private readonly InstructionHandleResult Result; + + + /********* + ** Accessors + *********/ + /// A brief noun phrase indicating what the instruction finder matches. + public string NounPhrase { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The full type name for which to find references. + /// The property name for which to find references. + /// The result to return for matching instructions. + public PropertyFinder(string fullTypeName, string propertyName, InstructionHandleResult result) + { + this.FullTypeName = fullTypeName; + this.PropertyName = propertyName; + this.Result = result; + this.NounPhrase = $"{fullTypeName}.{propertyName} property"; + } + + /// Perform the predefined logic for a method if applicable. + /// The assembly module containing the instruction. + /// The method definition containing the instruction. + /// Metadata for mapping assemblies to the current platform. + /// Whether the mod was compiled on a different platform. + public virtual InstructionHandleResult Handle(ModuleDefinition module, MethodDefinition method, PlatformAssemblyMap assemblyMap, bool platformChanged) + { + return InstructionHandleResult.None; + } + + /// Perform the predefined logic for an instruction if applicable. + /// 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 virtual InstructionHandleResult Handle(ModuleDefinition module, ILProcessor cil, Instruction instruction, PlatformAssemblyMap assemblyMap, bool platformChanged) + { + return this.IsMatch(instruction) + ? this.Result + : InstructionHandleResult.None; + } + + + /********* + ** Protected methods + *********/ + /// Get whether a CIL instruction matches. + /// The IL instruction. + protected bool IsMatch(Instruction instruction) + { + MethodReference methodRef = RewriteHelper.AsMethodReference(instruction); + return + methodRef != null + && methodRef.DeclaringType.FullName == this.FullTypeName + && (methodRef.Name == "get_" + this.PropertyName || methodRef.Name == "set_" + this.PropertyName); + } + } +} diff --git a/src/SMAPI/Framework/ModLoading/Finders/TypeFinder.cs b/src/SMAPI/Framework/ModLoading/Finders/TypeFinder.cs new file mode 100644 index 00000000..45349def --- /dev/null +++ b/src/SMAPI/Framework/ModLoading/Finders/TypeFinder.cs @@ -0,0 +1,133 @@ +using System.Linq; +using Mono.Cecil; +using Mono.Cecil.Cil; + +namespace StardewModdingAPI.Framework.ModLoading.Finders +{ + /// Finds incompatible CIL instructions that reference a given type. + internal class TypeFinder : IInstructionHandler + { + /********* + ** Accessors + *********/ + /// The full type name for which to find references. + private readonly string FullTypeName; + + /// The result to return for matching instructions. + private readonly InstructionHandleResult Result; + + + /********* + ** Accessors + *********/ + /// A brief noun phrase indicating what the instruction finder matches. + public string NounPhrase { get; } + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// The full type name to match. + /// The result to return for matching instructions. + public TypeFinder(string fullTypeName, InstructionHandleResult result) + { + this.FullTypeName = fullTypeName; + this.Result = result; + this.NounPhrase = $"{fullTypeName} type"; + } + + /// Perform the predefined logic for a method if applicable. + /// The assembly module containing the instruction. + /// The method definition containing the instruction. + /// Metadata for mapping assemblies to the current platform. + /// Whether the mod was compiled on a different platform. + public virtual InstructionHandleResult Handle(ModuleDefinition module, MethodDefinition method, PlatformAssemblyMap assemblyMap, bool platformChanged) + { + return this.IsMatch(method) + ? this.Result + : InstructionHandleResult.None; + } + + /// Perform the predefined logic for an instruction if applicable. + /// 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 virtual InstructionHandleResult Handle(ModuleDefinition module, ILProcessor cil, Instruction instruction, PlatformAssemblyMap assemblyMap, bool platformChanged) + { + return this.IsMatch(instruction) + ? this.Result + : InstructionHandleResult.None; + } + + + /********* + ** Protected methods + *********/ + /// Get whether a CIL instruction matches. + /// The method deifnition. + protected bool IsMatch(MethodDefinition method) + { + if (this.IsMatch(method.ReturnType)) + return true; + + foreach (VariableDefinition variable in method.Body.Variables) + { + if (this.IsMatch(variable.VariableType)) + return true; + } + + return false; + } + + /// Get whether a CIL instruction matches. + /// The IL instruction. + protected bool IsMatch(Instruction instruction) + { + // field reference + FieldReference fieldRef = RewriteHelper.AsFieldReference(instruction); + if (fieldRef != null) + { + return + this.IsMatch(fieldRef.DeclaringType) // field on target class + || this.IsMatch(fieldRef.FieldType); // field value is target class + } + + // method reference + MethodReference methodRef = RewriteHelper.AsMethodReference(instruction); + if (methodRef != null) + { + return + this.IsMatch(methodRef.DeclaringType) // method on target class + || this.IsMatch(methodRef.ReturnType) // method returns target class + || methodRef.Parameters.Any(p => this.IsMatch(p.ParameterType)); // method parameters + } + + return false; + } + + /// Get whether a type reference matches the expected type. + /// The type to check. + protected bool IsMatch(TypeReference type) + { + // root type + if (type.FullName == this.FullTypeName) + return true; + + // generic arguments + if (type is GenericInstanceType genericType) + { + if (genericType.GenericArguments.Any(this.IsMatch)) + return true; + } + + // generic parameters (e.g. constraints) + if (type.GenericParameters.Any(this.IsMatch)) + return true; + + return false; + } + } +} -- cgit