add trace logs when rewriting an assembly (#166)
This commit is contained in:
parent
8917fb6697
commit
0d94c628bb
|
@ -23,6 +23,9 @@ namespace StardewModdingAPI.Framework.AssemblyRewriting
|
|||
/// <summary>An assembly => reference cache.</summary>
|
||||
private readonly IDictionary<Assembly, AssemblyNameReference> AssemblyNameReferences;
|
||||
|
||||
/// <summary>Encapsulates monitoring and logging.</summary>
|
||||
private readonly IMonitor Monitor;
|
||||
|
||||
|
||||
/*********
|
||||
** Public methods
|
||||
|
@ -30,11 +33,13 @@ namespace StardewModdingAPI.Framework.AssemblyRewriting
|
|||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="targetAssemblies">The assembly filenames to target. Equivalent types will be rewritten to use these assemblies.</param>
|
||||
/// <param name="removeAssemblyNames">The short assembly names to remove as assembly reference, and replace with the <paramref name="targetAssemblies"/>.</param>
|
||||
public AssemblyTypeRewriter(Assembly[] targetAssemblies, string[] removeAssemblyNames)
|
||||
/// <param name="monitor">Encapsulates monitoring and logging.</param>
|
||||
public AssemblyTypeRewriter(Assembly[] targetAssemblies, string[] removeAssemblyNames, IMonitor monitor)
|
||||
{
|
||||
// save config
|
||||
this.TargetAssemblies = targetAssemblies;
|
||||
this.RemoveAssemblyNames = removeAssemblyNames;
|
||||
this.Monitor = monitor;
|
||||
|
||||
// cache assembly metadata
|
||||
this.AssemblyNameReferences = targetAssemblies.ToDictionary(assembly => assembly, assembly => AssemblyNameReference.Parse(assembly.FullName));
|
||||
|
@ -62,31 +67,39 @@ namespace StardewModdingAPI.Framework.AssemblyRewriting
|
|||
/// <param name="assembly">The assembly to rewrite.</param>
|
||||
public void RewriteAssembly(AssemblyDefinition assembly)
|
||||
{
|
||||
foreach (ModuleDefinition module in assembly.Modules)
|
||||
ModuleDefinition module = assembly.Modules.Single(); // technically an assembly can have multiple modules, but none of the build tools (including MSBuild) support it; simplify by assuming one module
|
||||
bool shouldRewrite = false;
|
||||
|
||||
// remove old assembly references
|
||||
for (int i = 0; i < module.AssemblyReferences.Count; i++)
|
||||
{
|
||||
// remove old assembly references
|
||||
bool shouldRewrite = false;
|
||||
for (int i = 0; i < module.AssemblyReferences.Count; i++)
|
||||
bool shouldRemove = this.RemoveAssemblyNames.Any(name => module.AssemblyReferences[i].Name == name);
|
||||
if (shouldRemove)
|
||||
{
|
||||
bool shouldRemove = this.RemoveAssemblyNames.Any(name => module.AssemblyReferences[i].Name == name);
|
||||
if (shouldRemove)
|
||||
{
|
||||
shouldRewrite = true;
|
||||
module.AssemblyReferences.RemoveAt(i);
|
||||
i--;
|
||||
}
|
||||
this.Monitor.Log($"removing reference to {module.AssemblyReferences[i]}", LogLevel.Trace);
|
||||
shouldRewrite = true;
|
||||
module.AssemblyReferences.RemoveAt(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
// replace references
|
||||
if (shouldRewrite)
|
||||
{
|
||||
// add target assembly references
|
||||
foreach (AssemblyNameReference target in this.AssemblyNameReferences.Values)
|
||||
{
|
||||
this.Monitor.Log($" adding reference to {target}", LogLevel.Trace);
|
||||
module.AssemblyReferences.Add(target);
|
||||
}
|
||||
|
||||
// replace references
|
||||
if (shouldRewrite)
|
||||
// rewrite type scopes to use target assemblies
|
||||
IEnumerable<TypeReference> typeReferences = module.GetTypeReferences().OrderBy(p => p.FullName);
|
||||
string lastTypeLogged = null;
|
||||
foreach (TypeReference type in typeReferences)
|
||||
{
|
||||
// add target assembly references
|
||||
foreach (AssemblyNameReference target in this.AssemblyNameReferences.Values)
|
||||
module.AssemblyReferences.Add(target);
|
||||
|
||||
// rewrite type scopes to use target assemblies
|
||||
foreach (TypeReference type in module.GetTypeReferences())
|
||||
this.ChangeTypeScope(type);
|
||||
this.ChangeTypeScope(type, shouldLog: type.FullName != lastTypeLogged);
|
||||
lastTypeLogged = type.FullName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +110,8 @@ namespace StardewModdingAPI.Framework.AssemblyRewriting
|
|||
*********/
|
||||
/// <summary>Get the correct reference to use for compatibility with the current platform.</summary>
|
||||
/// <param name="type">The type reference to rewrite.</param>
|
||||
private void ChangeTypeScope(TypeReference type)
|
||||
/// <param name="shouldLog">Whether to log a message.</param>
|
||||
private void ChangeTypeScope(TypeReference type, bool shouldLog)
|
||||
{
|
||||
// check skip conditions
|
||||
if (type == null || type.FullName.StartsWith("System."))
|
||||
|
@ -110,6 +124,8 @@ namespace StardewModdingAPI.Framework.AssemblyRewriting
|
|||
|
||||
// replace scope
|
||||
AssemblyNameReference assemblyRef = this.AssemblyNameReferences[assembly];
|
||||
if (shouldLog)
|
||||
this.Monitor.Log($"redirecting {type.FullName} from {type.Scope.Name} to {assemblyRef.Name}", LogLevel.Trace);
|
||||
type.Scope = assemblyRef;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace StardewModdingAPI.Framework
|
|||
/// <summary>Rewrites assembly types to match the current platform.</summary>
|
||||
private readonly AssemblyTypeRewriter AssemblyTypeRewriter;
|
||||
|
||||
/// <summary>Encapsulates monitoring and logging for a given module.</summary>
|
||||
/// <summary>Encapsulates monitoring and logging.</summary>
|
||||
private readonly IMonitor Monitor;
|
||||
|
||||
|
||||
|
@ -30,7 +30,7 @@ namespace StardewModdingAPI.Framework
|
|||
/// <summary>Construct an instance.</summary>
|
||||
/// <param name="cacheDirPath">The cache directory.</param>
|
||||
/// <param name="targetPlatform">The current game platform.</param>
|
||||
/// <param name="monitor">Encapsulates monitoring and logging for a given module.</param>
|
||||
/// <param name="monitor">Encapsulates monitoring and logging.</param>
|
||||
public ModAssemblyLoader(string cacheDirPath, Platform targetPlatform, IMonitor monitor)
|
||||
{
|
||||
this.CacheDirPath = cacheDirPath;
|
||||
|
@ -55,7 +55,7 @@ namespace StardewModdingAPI.Framework
|
|||
// process assembly if not cached
|
||||
if (!canUseCache)
|
||||
{
|
||||
this.Monitor.Log($"Preprocessing new assembly {assemblyFileName}...");
|
||||
this.Monitor.Log($"Loading {assemblyFileName} for the first time; preprocessing...");
|
||||
|
||||
// read assembly definition
|
||||
AssemblyDefinition assembly;
|
||||
|
@ -155,7 +155,7 @@ namespace StardewModdingAPI.Framework
|
|||
throw new InvalidOperationException($"Unknown target platform '{targetPlatform}'.");
|
||||
}
|
||||
|
||||
return new AssemblyTypeRewriter(targetAssemblies, removeAssemblyReferences);
|
||||
return new AssemblyTypeRewriter(targetAssemblies, removeAssemblyReferences, this.Monitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue