summaryrefslogtreecommitdiff
path: root/src/SMAPI/Framework/Deprecations/DeprecationManager.cs
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2022-05-15 01:54:01 -0400
committerJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2022-05-15 01:54:01 -0400
commit048f41244f6b2c7f95ac5bf75be2b16f42b99169 (patch)
tree59f6937d63653a7cb3ec04fde9f76539429a7854 /src/SMAPI/Framework/Deprecations/DeprecationManager.cs
parent3a4758dfa63f0f8e03166bffa15e16f7995499d7 (diff)
downloadSMAPI-048f41244f6b2c7f95ac5bf75be2b16f42b99169.tar.gz
SMAPI-048f41244f6b2c7f95ac5bf75be2b16f42b99169.tar.bz2
SMAPI-048f41244f6b2c7f95ac5bf75be2b16f42b99169.zip
reduce performance impact of deprecation warnings
Creating a stack is *very* slow, so it should be avoided if possible until after the duplicate-warning check.
Diffstat (limited to 'src/SMAPI/Framework/Deprecations/DeprecationManager.cs')
-rw-r--r--src/SMAPI/Framework/Deprecations/DeprecationManager.cs41
1 files changed, 27 insertions, 14 deletions
diff --git a/src/SMAPI/Framework/Deprecations/DeprecationManager.cs b/src/SMAPI/Framework/Deprecations/DeprecationManager.cs
index 288abde2..3bbbd7b8 100644
--- a/src/SMAPI/Framework/Deprecations/DeprecationManager.cs
+++ b/src/SMAPI/Framework/Deprecations/DeprecationManager.cs
@@ -37,13 +37,6 @@ namespace StardewModdingAPI.Framework.Deprecations
this.ModRegistry = modRegistry;
}
- /// <summary>Get a mod 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>
- public IModMetadata? GetModFromStack()
- {
- return this.ModRegistry.GetFromStack();
- }
-
/// <summary>Get a mod from its unique ID.</summary>
/// <param name="modId">The mod's unique ID.</param>
public IModMetadata? GetMod(string modId)
@@ -52,7 +45,7 @@ namespace StardewModdingAPI.Framework.Deprecations
}
/// <summary>Log a deprecation warning.</summary>
- /// <param name="source">The mod which used the deprecated code, if known.</param>
+ /// <param name="source">The mod which used the deprecated code, or <c>null</c> to get it heuristically. Note that getting it heuristically is very slow in some cases, and should be avoided if at all possible.</param>
/// <param name="nounPhrase">A noun phrase describing what is deprecated.</param>
/// <param name="version">The SMAPI version which deprecated it.</param>
/// <param name="severity">How deprecated the code is.</param>
@@ -60,18 +53,38 @@ namespace StardewModdingAPI.Framework.Deprecations
/// <param name="logStackTrace">Whether to log a stack trace showing where the deprecated code is in the mod.</param>
public void Warn(IModMetadata? source, string nounPhrase, string version, DeprecationLevel severity, string[]? unlessStackIncludes = null, bool logStackTrace = true)
{
+ // get heuristic source
+ // The call stack is usually the most reliable way to get the source if it's unknown. This is *very* slow
+ // though, especially before we check whether this is a duplicate warning. The initial cache check uses a
+ // quick heuristic method if at all possible to avoid that.
+ IModMetadata? heuristicSource = source;
+ ImmutableStackTrace? stack = null;
+ if (heuristicSource is null)
+ Context.HeuristicModsRunningCode.TryPeek(out heuristicSource);
+ if (heuristicSource is null)
+ {
+ stack = ImmutableStackTrace.Get(skipFrames: 1);
+ heuristicSource = this.ModRegistry.GetFromStack(stack.GetFrames());
+ }
+
// skip if already warned
- string cacheKey = $"{source?.DisplayName ?? "<unknown>"}::{nounPhrase}::{version}";
+ string cacheKey = $"{heuristicSource?.Manifest.UniqueID ?? "<unknown>"}::{nounPhrase}::{version}";
if (this.LoggedDeprecations.Contains(cacheKey))
return;
+ this.LoggedDeprecations.Add(cacheKey);
- // warn if valid
- ImmutableStackTrace stack = ImmutableStackTrace.Get(skipFrames: 1);
- if (!this.ShouldSuppress(stack, unlessStackIncludes))
+ // get more accurate source
+ if (stack is not null)
+ source ??= heuristicSource!;
+ else
{
- this.LoggedDeprecations.Add(cacheKey);
- this.QueuedWarnings.Add(new DeprecationWarning(source, nounPhrase, version, severity, stack, logStackTrace));
+ stack ??= ImmutableStackTrace.Get(skipFrames: 1);
+ source ??= this.ModRegistry.GetFromStack(stack.GetFrames());
}
+
+ // log unless suppressed
+ if (!this.ShouldSuppress(stack, unlessStackIncludes))
+ this.QueuedWarnings.Add(new DeprecationWarning(source, nounPhrase, version, severity, stack, logStackTrace));
}
/// <summary>A placeholder method used to track deprecated code for which a separate warning will be shown.</summary>