diff options
Diffstat (limited to 'src/SMAPI/Framework/ModLoading/Finders')
5 files changed, 86 insertions, 44 deletions
diff --git a/src/SMAPI/Framework/ModLoading/Finders/EventFinder.cs b/src/SMAPI/Framework/ModLoading/Finders/EventFinder.cs index 01ed153b..a2ea3232 100644 --- a/src/SMAPI/Framework/ModLoading/Finders/EventFinder.cs +++ b/src/SMAPI/Framework/ModLoading/Finders/EventFinder.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; +using System.Linq; using Mono.Cecil; using Mono.Cecil.Cil; using StardewModdingAPI.Framework.ModLoading.Framework; @@ -13,8 +15,8 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders /// <summary>The full type name for which to find references.</summary> private readonly string FullTypeName; - /// <summary>The event name for which to find references.</summary> - private readonly string EventName; + /// <summary>The method names for which to find references.</summary> + private readonly ISet<string> MethodNames; /// <summary>The result to return for matching instructions.</summary> private readonly InstructionHandleResult Result; @@ -25,38 +27,47 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders *********/ /// <summary>Construct an instance.</summary> /// <param name="fullTypeName">The full type name for which to find references.</param> - /// <param name="eventName">The event name for which to find references.</param> + /// <param name="eventNames">The event names for which to find references.</param> /// <param name="result">The result to return for matching instructions.</param> - public EventFinder(string fullTypeName, string eventName, InstructionHandleResult result) - : base(defaultPhrase: $"{fullTypeName}.{eventName} event") + public EventFinder(string fullTypeName, string[] eventNames, InstructionHandleResult result) + : base(defaultPhrase: $"{string.Join(", ", eventNames.Select(p => $"{fullTypeName}.{p}"))} event{(eventNames.Length != 1 ? "s" : "")}") // default phrase should never be used { this.FullTypeName = fullTypeName; - this.EventName = eventName; this.Result = result; + + this.MethodNames = new HashSet<string>(); + foreach (string name in eventNames) + { + this.MethodNames.Add($"add_{name}"); + this.MethodNames.Add($"remove_{name}"); + } } + /// <summary>Construct an instance.</summary> + /// <param name="fullTypeName">The full type name for which to find references.</param> + /// <param name="eventName">The event name for which to find references.</param> + /// <param name="result">The result to return for matching instructions.</param> + public EventFinder(string fullTypeName, string eventName, InstructionHandleResult result) + : this(fullTypeName, new[] { eventName }, result) { } + /// <inheritdoc /> public override bool Handle(ModuleDefinition module, ILProcessor cil, Instruction instruction) { - if (!this.Flags.Contains(this.Result) && this.IsMatch(instruction)) - this.MarkFlag(this.Result); - - return false; - } + if (this.MethodNames.Any()) + { + MethodReference methodRef = RewriteHelper.AsMethodReference(instruction); + if (methodRef is not null && methodRef.DeclaringType.FullName == this.FullTypeName && this.MethodNames.Contains(methodRef.Name)) + { + string eventName = methodRef.Name.Split(new[] { '_' }, 2)[1]; + this.MethodNames.Remove($"add_{eventName}"); + this.MethodNames.Remove($"remove_{eventName}"); + this.MarkFlag(this.Result); + this.Phrases.Add($"{this.FullTypeName}.{eventName} event"); + } + } - /********* - ** Protected methods - *********/ - /// <summary>Get whether a CIL instruction matches.</summary> - /// <param name="instruction">The IL instruction.</param> - 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); + return false; } } } diff --git a/src/SMAPI/Framework/ModLoading/Finders/FieldFinder.cs b/src/SMAPI/Framework/ModLoading/Finders/FieldFinder.cs index 2c062243..0947062c 100644 --- a/src/SMAPI/Framework/ModLoading/Finders/FieldFinder.cs +++ b/src/SMAPI/Framework/ModLoading/Finders/FieldFinder.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; +using System.Linq; using Mono.Cecil; using Mono.Cecil.Cil; using StardewModdingAPI.Framework.ModLoading.Framework; @@ -13,8 +15,8 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders /// <summary>The full type name for which to find references.</summary> private readonly string FullTypeName; - /// <summary>The field name for which to find references.</summary> - private readonly string FieldName; + /// <summary>The field names for which to find references.</summary> + private readonly ISet<string> FieldNames; /// <summary>The result to return for matching instructions.</summary> private readonly InstructionHandleResult Result; @@ -25,21 +27,37 @@ namespace StardewModdingAPI.Framework.ModLoading.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="fieldNames">The field names for which to find references.</param> /// <param name="result">The result to return for matching instructions.</param> - public FieldFinder(string fullTypeName, string fieldName, InstructionHandleResult result) - : base(defaultPhrase: $"{fullTypeName}.{fieldName} field") + public FieldFinder(string fullTypeName, string[] fieldNames, InstructionHandleResult result) + : base(defaultPhrase: $"{string.Join(", ", fieldNames.Select(p => $"{fullTypeName}.{p}"))} field{(fieldNames.Length != 1 ? "s" : "")}") // default phrase should never be used { this.FullTypeName = fullTypeName; - this.FieldName = fieldName; + this.FieldNames = new HashSet<string>(fieldNames); this.Result = result; } + /// <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="result">The result to return for matching instructions.</param> + public FieldFinder(string fullTypeName, string fieldName, InstructionHandleResult result) + : this(fullTypeName, new[] { fieldName }, result) { } + /// <inheritdoc /> public override bool Handle(ModuleDefinition module, ILProcessor cil, Instruction instruction) { - if (!this.Flags.Contains(this.Result) && RewriteHelper.IsFieldReferenceTo(instruction, this.FullTypeName, this.FieldName)) - this.MarkFlag(this.Result); + if (this.FieldNames.Any()) + { + FieldReference fieldRef = RewriteHelper.AsFieldReference(instruction); + if (fieldRef is not null && fieldRef.DeclaringType.FullName == this.FullTypeName && this.FieldNames.Contains(fieldRef.Name)) + { + this.FieldNames.Remove(fieldRef.Name); + + this.MarkFlag(this.Result); + this.Phrases.Add($"{this.FullTypeName}.{fieldRef.Name} field"); + } + } return false; } diff --git a/src/SMAPI/Framework/ModLoading/Finders/ReferenceToMemberWithUnexpectedTypeFinder.cs b/src/SMAPI/Framework/ModLoading/Finders/ReferenceToMemberWithUnexpectedTypeFinder.cs index b01a3240..8c1cae2b 100644 --- a/src/SMAPI/Framework/ModLoading/Finders/ReferenceToMemberWithUnexpectedTypeFinder.cs +++ b/src/SMAPI/Framework/ModLoading/Finders/ReferenceToMemberWithUnexpectedTypeFinder.cs @@ -14,7 +14,7 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders ** Fields *********/ /// <summary>The assembly names to which to heuristically detect broken references.</summary> - private readonly HashSet<string> ValidateReferencesToAssemblies; + private readonly ISet<string> ValidateReferencesToAssemblies; /********* @@ -22,10 +22,10 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders *********/ /// <summary>Construct an instance.</summary> /// <param name="validateReferencesToAssemblies">The assembly names to which to heuristically detect broken references.</param> - public ReferenceToMemberWithUnexpectedTypeFinder(string[] validateReferencesToAssemblies) + public ReferenceToMemberWithUnexpectedTypeFinder(ISet<string> validateReferencesToAssemblies) : base(defaultPhrase: "") { - this.ValidateReferencesToAssemblies = new HashSet<string>(validateReferencesToAssemblies); + this.ValidateReferencesToAssemblies = validateReferencesToAssemblies; } /// <inheritdoc /> diff --git a/src/SMAPI/Framework/ModLoading/Finders/ReferenceToMissingMemberFinder.cs b/src/SMAPI/Framework/ModLoading/Finders/ReferenceToMissingMemberFinder.cs index b64a255e..d305daf4 100644 --- a/src/SMAPI/Framework/ModLoading/Finders/ReferenceToMissingMemberFinder.cs +++ b/src/SMAPI/Framework/ModLoading/Finders/ReferenceToMissingMemberFinder.cs @@ -13,7 +13,7 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders ** Fields *********/ /// <summary>The assembly names to which to heuristically detect broken references.</summary> - private readonly HashSet<string> ValidateReferencesToAssemblies; + private readonly ISet<string> ValidateReferencesToAssemblies; /********* @@ -21,10 +21,10 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders *********/ /// <summary>Construct an instance.</summary> /// <param name="validateReferencesToAssemblies">The assembly names to which to heuristically detect broken references.</param> - public ReferenceToMissingMemberFinder(string[] validateReferencesToAssemblies) + public ReferenceToMissingMemberFinder(ISet<string> validateReferencesToAssemblies) : base(defaultPhrase: "") { - this.ValidateReferencesToAssemblies = new HashSet<string>(validateReferencesToAssemblies); + this.ValidateReferencesToAssemblies = validateReferencesToAssemblies; } /// <inheritdoc /> diff --git a/src/SMAPI/Framework/ModLoading/Finders/TypeFinder.cs b/src/SMAPI/Framework/ModLoading/Finders/TypeFinder.cs index bbd081e8..260a8df8 100644 --- a/src/SMAPI/Framework/ModLoading/Finders/TypeFinder.cs +++ b/src/SMAPI/Framework/ModLoading/Finders/TypeFinder.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Mono.Cecil; using StardewModdingAPI.Framework.ModLoading.Framework; @@ -10,8 +11,8 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders /********* ** Fields *********/ - /// <summary>The full type name to match.</summary> - private readonly string FullTypeName; + /// <summary>The full type names remaining to match.</summary> + private readonly ISet<string> FullTypeNames; /// <summary>The result to return for matching instructions.</summary> private readonly InstructionHandleResult Result; @@ -24,22 +25,34 @@ namespace StardewModdingAPI.Framework.ModLoading.Finders ** Public methods *********/ /// <summary>Construct an instance.</summary> - /// <param name="fullTypeName">The full type name to match.</param> + /// <param name="fullTypeNames">The full type names to match.</param> /// <param name="result">The result to return for matching instructions.</param> /// <param name="shouldIgnore">Get whether a matched type should be ignored.</param> - public TypeFinder(string fullTypeName, InstructionHandleResult result, Func<TypeReference, bool> shouldIgnore = null) - : base(defaultPhrase: $"{fullTypeName} type") + public TypeFinder(string[] fullTypeNames, InstructionHandleResult result, Func<TypeReference, bool> shouldIgnore = null) + : base(defaultPhrase: $"{string.Join(", ", fullTypeNames)} type{(fullTypeNames.Length != 1 ? "s" : "")}") // default phrase should never be used { - this.FullTypeName = fullTypeName; + this.FullTypeNames = new HashSet<string>(fullTypeNames); this.Result = result; this.ShouldIgnore = shouldIgnore; } + /// <summary>Construct an instance.</summary> + /// <param name="fullTypeName">The full type name to match.</param> + /// <param name="result">The result to return for matching instructions.</param> + /// <param name="shouldIgnore">Get whether a matched type should be ignored.</param> + public TypeFinder(string fullTypeName, InstructionHandleResult result, Func<TypeReference, bool> shouldIgnore = null) + : this(new[] { fullTypeName }, result, shouldIgnore) { } + /// <inheritdoc /> public override bool Handle(ModuleDefinition module, TypeReference type, Action<TypeReference> replaceWith) { - if (type.FullName == this.FullTypeName && this.ShouldIgnore?.Invoke(type) != true) + if (this.FullTypeNames.Contains(type.FullName) && this.ShouldIgnore?.Invoke(type) != true) + { + this.FullTypeNames.Remove(type.FullName); + this.MarkFlag(this.Result); + this.Phrases.Add($"{type.FullName} type"); + } return false; } |