From 6a6c484b9867524d2eaa617da4dde36fec8c3110 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Wed, 28 Jul 2021 00:49:54 -0400 Subject: add accessed key to dictionary KeyNotFoundException message --- src/SMAPI.Mods.ErrorHandler/ModEntry.cs | 1 + .../Patches/DictionaryPatches.cs | 81 ++++++++++++++++++++++ .../SMAPI.Mods.ErrorHandler.csproj | 1 + 3 files changed, 83 insertions(+) create mode 100644 src/SMAPI.Mods.ErrorHandler/Patches/DictionaryPatches.cs (limited to 'src/SMAPI.Mods.ErrorHandler') diff --git a/src/SMAPI.Mods.ErrorHandler/ModEntry.cs b/src/SMAPI.Mods.ErrorHandler/ModEntry.cs index d9426d75..719eddab 100644 --- a/src/SMAPI.Mods.ErrorHandler/ModEntry.cs +++ b/src/SMAPI.Mods.ErrorHandler/ModEntry.cs @@ -31,6 +31,7 @@ namespace StardewModdingAPI.Mods.ErrorHandler // apply patches new GamePatcher(this.Monitor).Apply( new DialogueErrorPatch(monitorForGame, this.Helper.Reflection), + new DictionaryPatches(this.Helper.Reflection), new EventPatches(monitorForGame), new GameLocationPatches(monitorForGame), new ObjectErrorPatch(), diff --git a/src/SMAPI.Mods.ErrorHandler/Patches/DictionaryPatches.cs b/src/SMAPI.Mods.ErrorHandler/Patches/DictionaryPatches.cs new file mode 100644 index 00000000..ce88999d --- /dev/null +++ b/src/SMAPI.Mods.ErrorHandler/Patches/DictionaryPatches.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using HarmonyLib; +using StardewModdingAPI.Framework.Patching; +using StardewValley.GameData; +using StardewValley.GameData.HomeRenovations; +using StardewValley.GameData.Movies; + +namespace StardewModdingAPI.Mods.ErrorHandler.Patches +{ + /// A Harmony patch for which adds the accessed key to exceptions. + /// Patch methods must be static for Harmony to work correctly. See the Harmony documentation before renaming patch arguments. + [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony and methods are named for clarity.")] + [SuppressMessage("ReSharper", "IdentifierTypo", Justification = "Argument names are defined by Harmony and methods are named for clarity.")] + internal class DictionaryPatches : IHarmonyPatch + { + /********* + ** Fields + *********/ + /// Simplifies access to private code. + private static IReflectionHelper Reflection; + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// Simplifies access to private code. + public DictionaryPatches(IReflectionHelper reflector) + { + DictionaryPatches.Reflection = reflector; + } + + /// + public void Apply(Harmony harmony) + { + Type[] keyTypes = { typeof(int), typeof(string) }; + Type[] valueTypes = { typeof(int), typeof(string), typeof(HomeRenovation), typeof(MovieData), typeof(SpecialOrderData) }; + + foreach (Type keyType in keyTypes) + { + foreach (Type valueType in valueTypes) + { + Type dictionaryType = typeof(Dictionary<,>).MakeGenericType(keyType, valueType); + + harmony.Patch( + original: AccessTools.Method(dictionaryType, "get_Item"), + finalizer: new HarmonyMethod(this.GetType(), nameof(DictionaryPatches.Finalize_GetItem)) + ); + } + } + } + + + /********* + ** Private methods + *********/ + /// The method to call after the dictionary indexer throws an exception. + /// The dictionary key being fetched. + /// The exception thrown by the wrapped method, if any. + /// Returns the exception to throw, if any. + private static Exception Finalize_GetItem(object key, Exception __exception) + { + if (__exception is KeyNotFoundException) + AddKeyTo(__exception, key?.ToString()); + + return __exception; + } + + /// Add the accessed key to an exception message. + /// The exception to modify. + /// The dictionary key. + private static void AddKeyTo(Exception exception, string key) + { + DictionaryPatches.Reflection + .GetField(exception, "_message") + .SetValue($"{exception.Message}\nkey: '{key}'"); + } + } +} diff --git a/src/SMAPI.Mods.ErrorHandler/SMAPI.Mods.ErrorHandler.csproj b/src/SMAPI.Mods.ErrorHandler/SMAPI.Mods.ErrorHandler.csproj index 006a09ca..531d3699 100644 --- a/src/SMAPI.Mods.ErrorHandler/SMAPI.Mods.ErrorHandler.csproj +++ b/src/SMAPI.Mods.ErrorHandler/SMAPI.Mods.ErrorHandler.csproj @@ -15,6 +15,7 @@ + -- cgit