summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'src/SMAPI/Framework')
-rw-r--r--src/SMAPI/Framework/DeprecationManager.cs45
-rw-r--r--src/SMAPI/Framework/ModRegistry.cs20
2 files changed, 56 insertions, 9 deletions
diff --git a/src/SMAPI/Framework/DeprecationManager.cs b/src/SMAPI/Framework/DeprecationManager.cs
index c80fdce7..37a5c8ef 100644
--- a/src/SMAPI/Framework/DeprecationManager.cs
+++ b/src/SMAPI/Framework/DeprecationManager.cs
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
+using System.Text;
namespace StardewModdingAPI.Framework
{
@@ -62,7 +63,8 @@ namespace StardewModdingAPI.Framework
return;
// queue warning
- this.QueuedWarnings.Add(new DeprecationWarning(source, nounPhrase, version, severity, new StackTrace(skipFrames: 1)));
+ var stack = new StackTrace(skipFrames: 1); // skip this method
+ this.QueuedWarnings.Add(new DeprecationWarning(source, nounPhrase, version, severity, stack));
}
/// <summary>A placeholder method used to track deprecated code for which a separate warning will be shown.</summary>
@@ -100,11 +102,11 @@ namespace StardewModdingAPI.Framework
// log message
if (level == LogLevel.Trace)
- this.Monitor.Log($"{message}\n{warning.StackTrace}", level);
+ this.Monitor.Log($"{message}\n{this.GetSimplifiedStackTrace(warning.StackTrace, warning.Mod)}", level);
else
{
this.Monitor.Log(message, level);
- this.Monitor.Log(warning.StackTrace.ToString(), LogLevel.Debug);
+ this.Monitor.Log(this.GetSimplifiedStackTrace(warning.StackTrace, warning.Mod), LogLevel.Debug);
}
}
@@ -128,5 +130,42 @@ namespace StardewModdingAPI.Framework
this.LoggedDeprecations.Add(key);
return true;
}
+
+ /// <summary>Get the simplest stack trace which shows where in the mod the deprecated code was called from.</summary>
+ /// <param name="stack">The stack trace.</param>
+ /// <param name="mod">The mod for which to show a stack trace.</param>
+ private string GetSimplifiedStackTrace(StackTrace stack, IModMetadata? mod)
+ {
+ // unknown mod, show entire stack trace
+ if (mod == null)
+ return stack.ToString();
+
+ // get frame info
+ var frames = stack
+ .GetFrames()
+ .Select(frame => (Frame: frame, Mod: this.ModRegistry.GetFrom(frame)))
+ .ToArray();
+ var modIds = new HashSet<string>(
+ from frame in frames
+ let id = frame.Mod?.Manifest.UniqueID
+ where id != null
+ select id
+ );
+
+ // can't filter to the target mod
+ if (modIds.Count != 1 || !modIds.Contains(mod.Manifest.UniqueID))
+ return stack.ToString();
+
+ // get stack frames for the target mod, plus one for context
+ var framesStartingAtMod = frames.SkipWhile(p => p.Mod == null).ToArray();
+ var displayFrames = framesStartingAtMod.TakeWhile(p => p.Mod != null).ToArray();
+ displayFrames = displayFrames.Concat(framesStartingAtMod.Skip(displayFrames.Length).Take(1)).ToArray();
+
+ // build stack trace
+ StringBuilder str = new();
+ foreach (var frame in displayFrames)
+ str.Append(new StackTrace(frame.Frame));
+ return str.ToString().TrimEnd();
+ }
}
}
diff --git a/src/SMAPI/Framework/ModRegistry.cs b/src/SMAPI/Framework/ModRegistry.cs
index de16a780..449dccb1 100644
--- a/src/SMAPI/Framework/ModRegistry.cs
+++ b/src/SMAPI/Framework/ModRegistry.cs
@@ -59,7 +59,7 @@ namespace StardewModdingAPI.Framework
/// <summary>Get metadata for a loaded mod.</summary>
/// <param name="uniqueID">The mod's unique ID.</param>
- /// <returns>Returns the matching mod's metadata, or <c>null</c> if not found.</returns>
+ /// <returns>Returns the mod's metadata, or <c>null</c> if not found.</returns>
public IModMetadata? Get(string uniqueID)
{
// normalize search ID
@@ -73,7 +73,7 @@ namespace StardewModdingAPI.Framework
/// <summary>Get the mod metadata from one of its assemblies.</summary>
/// <param name="type">The type to check.</param>
- /// <returns>Returns the mod name, or <c>null</c> if the type isn't part of a known mod.</returns>
+ /// <returns>Returns the mod's metadata, or <c>null</c> if the type isn't part of a known mod.</returns>
public IModMetadata? GetFrom(Type? type)
{
// null
@@ -89,8 +89,17 @@ namespace StardewModdingAPI.Framework
return null;
}
- /// <summary>Get the friendly name for the closest assembly registered as a source of deprecation warnings.</summary>
- /// <returns>Returns the source name, or <c>null</c> if no registered assemblies were found.</returns>
+ /// <summary>Get the mod metadata from a stack frame, if any.</summary>
+ /// <param name="frame">The stack frame to check.</param>
+ /// <returns>Returns the mod's metadata, or <c>null</c> if the frame isn't part of a known mod.</returns>
+ public IModMetadata? GetFrom(StackFrame frame)
+ {
+ MethodBase? method = frame.GetMethod();
+ return this.GetFrom(method?.ReflectedType);
+ }
+
+ /// <summary>Get the mod metadata from the closest assembly registered as a source of deprecation warnings.</summary>
+ /// <returns>Returns the mod's metadata, or <c>null</c> if no registered assemblies were found.</returns>
public IModMetadata? GetFromStack()
{
// get stack frames
@@ -100,8 +109,7 @@ namespace StardewModdingAPI.Framework
// search stack for a source assembly
foreach (StackFrame frame in frames)
{
- MethodBase? method = frame.GetMethod();
- IModMetadata? mod = this.GetFrom(method?.ReflectedType);
+ IModMetadata? mod = this.GetFrom(frame);
if (mod != null)
return mod;
}