288 lines
10 KiB
C#
Raw Normal View History

2024-06-12 00:07:44 -04:00
using AssemblyRemapper.Enums;
using AssemblyRemapper.Models;
2024-06-11 19:18:48 -04:00
using AssemblyRemapper.Utils;
using Mono.Cecil;
namespace AssemblyRemapper.Reflection;
internal class Remapper
{
2024-06-13 01:53:43 -04:00
/// <summary>
/// Start the remapping process
/// </summary>
2024-06-11 19:18:48 -04:00
public void InitializeRemap()
{
DisplayBasicModuleInformation();
2024-06-12 00:05:59 -04:00
foreach (var remap in DataProvider.Remaps)
2024-06-11 19:18:48 -04:00
{
2024-06-12 18:59:08 -04:00
Logger.Log($"Finding best match for {remap.NewTypeName}...", ConsoleColor.Gray);
2024-06-11 19:18:48 -04:00
HandleMapping(remap);
}
ChooseBestMatches();
if (DataProvider.AppSettings.ScoringMode) { return; }
// Dont publicize and unseal until after the remapping so we can use those as search parameters
Publicizer.Publicize();
Publicizer.Unseal();
2024-06-11 19:18:48 -04:00
// We are done, write the assembly
WriteAssembly();
}
2024-06-13 01:53:43 -04:00
/// <summary>
/// Display information about the module we are remapping
/// </summary>
2024-06-12 14:38:43 -04:00
private void DisplayBasicModuleInformation()
{
Logger.Log("-----------------------------------------------", ConsoleColor.Yellow);
Logger.Log($"Starting remap...", ConsoleColor.Yellow);
Logger.Log($"Module contains {DataProvider.ModuleDefinition.Types.Count} Types", ConsoleColor.Yellow);
Logger.Log($"Publicize: {DataProvider.AppSettings.Publicize}", ConsoleColor.Yellow);
Logger.Log($"Unseal: {DataProvider.AppSettings.Unseal}", ConsoleColor.Yellow);
Logger.Log("-----------------------------------------------", ConsoleColor.Yellow);
}
2024-06-13 01:53:43 -04:00
/// <summary>
/// Loop over all types in the assembly and score them
/// </summary>
/// <param name="mapping">Mapping to score</param>
2024-06-12 00:05:59 -04:00
private void HandleMapping(RemapModel mapping)
2024-06-11 19:18:48 -04:00
{
foreach (var type in DataProvider.ModuleDefinition.Types)
{
2024-06-12 18:59:08 -04:00
var result = ScoreType(type, mapping);
if (result is not EFailureReason.None)
{
//Logger.LogDebug($"Remap [{type.Name} : {mapping.NewTypeName}] failed with reason {result}", silent: true);
}
2024-06-11 19:18:48 -04:00
}
}
2024-06-13 01:53:43 -04:00
/// <summary>
/// Score the type against the remap checking against all remap properties
/// </summary>
/// <param name="type">Type to score</param>
/// <param name="remap">Remap to check against</param>
/// <param name="parentTypeName"></param>
/// <returns>Failure reason or none if matched</returns>
private EFailureReason ScoreType(TypeDefinition type, RemapModel remap)
2024-06-11 19:18:48 -04:00
{
2024-06-11 23:07:59 -04:00
// Handle Direct Remaps by strict naming first bypasses everything else
if (remap.UseForceRename)
{
HandleByDirectName(type, remap);
2024-06-12 18:59:08 -04:00
return EFailureReason.None;
2024-06-11 23:07:59 -04:00
}
2024-06-11 19:18:48 -04:00
foreach (var nestedType in type.NestedTypes)
{
2024-06-13 01:53:43 -04:00
ScoreType(nestedType, remap);
2024-06-11 19:18:48 -04:00
}
var score = new ScoringModel
{
ProposedNewName = remap.NewTypeName,
2024-06-13 01:46:51 -04:00
ReMap = remap,
2024-06-12 00:05:59 -04:00
Definition = type,
2024-06-11 19:18:48 -04:00
};
2024-06-12 14:38:43 -04:00
// Set the original type name to be used later
2024-06-13 01:46:51 -04:00
score.ReMap.OriginalTypeName = type.Name;
2024-06-12 14:38:43 -04:00
2024-06-11 19:18:48 -04:00
if (type.MatchIsAbstract(remap.SearchParams, score) == EMatchResult.NoMatch)
{
2024-06-13 01:46:51 -04:00
remap.FailureReason = EFailureReason.IsAbstract;
2024-06-12 18:59:08 -04:00
return EFailureReason.IsAbstract;
2024-06-11 19:18:48 -04:00
}
2024-06-12 00:05:59 -04:00
2024-06-11 19:18:48 -04:00
if (type.MatchIsEnum(remap.SearchParams, score) == EMatchResult.NoMatch)
{
2024-06-13 01:46:51 -04:00
remap.FailureReason = EFailureReason.IsEnum;
2024-06-12 18:59:08 -04:00
return EFailureReason.IsEnum;
2024-06-11 19:18:48 -04:00
}
if (type.MatchIsNested(remap.SearchParams, score) == EMatchResult.NoMatch)
{
2024-06-13 01:46:51 -04:00
remap.FailureReason = EFailureReason.IsNested;
2024-06-12 18:59:08 -04:00
return EFailureReason.IsNested;
2024-06-11 19:18:48 -04:00
}
if (type.MatchIsSealed(remap.SearchParams, score) == EMatchResult.NoMatch)
{
2024-06-13 01:46:51 -04:00
remap.FailureReason = EFailureReason.IsSealed;
2024-06-12 18:59:08 -04:00
return EFailureReason.IsSealed;
2024-06-11 19:18:48 -04:00
}
if (type.MatchIsDerived(remap.SearchParams, score) == EMatchResult.NoMatch)
{
2024-06-13 01:46:51 -04:00
remap.FailureReason = EFailureReason.IsDerived;
2024-06-12 18:59:08 -04:00
return EFailureReason.IsDerived;
2024-06-11 19:18:48 -04:00
}
if (type.MatchIsInterface(remap.SearchParams, score) == EMatchResult.NoMatch)
{
2024-06-13 01:46:51 -04:00
remap.FailureReason = EFailureReason.IsInterface;
2024-06-12 18:59:08 -04:00
return EFailureReason.IsInterface;
2024-06-11 19:18:48 -04:00
}
2024-06-12 18:59:08 -04:00
if (type.MatchHasGenericParameters(remap.SearchParams, score) == EMatchResult.NoMatch)
2024-06-11 19:18:48 -04:00
{
2024-06-13 01:46:51 -04:00
remap.FailureReason = EFailureReason.HasGenericParameters;
2024-06-12 18:59:08 -04:00
return EFailureReason.HasGenericParameters;
2024-06-11 19:18:48 -04:00
}
if (type.MatchIsPublic(remap.SearchParams, score) == EMatchResult.NoMatch)
{
2024-06-13 01:46:51 -04:00
remap.FailureReason = EFailureReason.IsPublic;
2024-06-12 18:59:08 -04:00
return EFailureReason.IsPublic;
2024-06-11 19:18:48 -04:00
}
if (type.MatchHasAttribute(remap.SearchParams, score) == EMatchResult.NoMatch)
{
2024-06-13 01:46:51 -04:00
remap.FailureReason = EFailureReason.HasAttribute;
2024-06-12 18:59:08 -04:00
return EFailureReason.HasAttribute;
2024-06-11 19:18:48 -04:00
}
if (type.MatchMethods(remap.SearchParams, score) == EMatchResult.NoMatch)
{
2024-06-13 01:46:51 -04:00
remap.FailureReason = EFailureReason.HasMethods;
2024-06-12 18:59:08 -04:00
return EFailureReason.HasMethods;
2024-06-11 19:18:48 -04:00
}
if (type.MatchFields(remap.SearchParams, score) == EMatchResult.NoMatch)
{
2024-06-13 01:46:51 -04:00
remap.FailureReason = EFailureReason.HasFields;
2024-06-12 18:59:08 -04:00
return EFailureReason.HasFields;
2024-06-11 19:18:48 -04:00
}
if (type.MatchProperties(remap.SearchParams, score) == EMatchResult.NoMatch)
{
2024-06-13 01:46:51 -04:00
remap.FailureReason = EFailureReason.HasProperties;
2024-06-12 18:59:08 -04:00
return EFailureReason.HasProperties;
2024-06-11 19:18:48 -04:00
}
if (type.MatchNestedTypes(remap.SearchParams, score) == EMatchResult.NoMatch)
{
2024-06-13 01:46:51 -04:00
remap.FailureReason = EFailureReason.HasNestedTypes;
2024-06-12 18:59:08 -04:00
return EFailureReason.HasNestedTypes;
2024-06-11 19:18:48 -04:00
}
2024-06-11 23:07:59 -04:00
remap.OriginalTypeName = type.Name;
2024-06-13 01:46:51 -04:00
remap.Succeeded = true;
remap.FailureReason = EFailureReason.None;
2024-06-12 19:42:16 -04:00
score.AddScoreToResult();
2024-06-12 18:59:08 -04:00
return EFailureReason.None;
2024-06-11 19:18:48 -04:00
}
2024-06-12 00:05:59 -04:00
private void HandleByDirectName(TypeDefinition type, RemapModel remap)
2024-06-11 23:07:59 -04:00
{
2024-06-12 00:05:59 -04:00
if (type.Name != remap.OriginalTypeName) { return; }
2024-06-11 23:07:59 -04:00
var oldName = type.Name;
remap.OriginalTypeName = type.Name;
2024-06-13 01:46:51 -04:00
remap.FailureReason = EFailureReason.None;
remap.Succeeded = true;
2024-06-12 22:31:41 -04:00
type.Name = remap.NewTypeName;
2024-06-12 14:38:43 -04:00
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
2024-06-11 23:07:59 -04:00
Logger.Log($"Renamed {oldName} to {type.Name} directly", ConsoleColor.Green);
2024-06-12 14:38:43 -04:00
2024-06-12 20:17:23 -04:00
Renamer.RenameAllDirect(remap, type);
2024-06-12 14:38:43 -04:00
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
2024-06-11 23:07:59 -04:00
}
2024-06-13 01:53:43 -04:00
/// <summary>
/// Choose the best possible match from all remaps
/// </summary>
2024-06-11 19:18:48 -04:00
private void ChooseBestMatches()
{
2024-06-11 23:07:59 -04:00
foreach (var score in DataProvider.ScoringModels)
2024-06-11 19:18:48 -04:00
{
2024-06-13 01:53:43 -04:00
ChooseBestMatch(score.Value);
2024-06-11 19:18:48 -04:00
}
2024-06-13 01:46:51 -04:00
var failures = 0;
var changes = 0;
foreach (var remap in DataProvider.Remaps)
{
if (remap.Succeeded is false)
{
Logger.Log("-----------------------------------------------", ConsoleColor.Red);
Logger.Log($"Renaming {remap.NewTypeName} failed with reason {remap.FailureReason}", ConsoleColor.Red);
Logger.Log("-----------------------------------------------", ConsoleColor.Red);
failures++;
return;
}
changes++;
}
Logger.Log("-----------------------------------------------", ConsoleColor.Yellow);
Logger.Log($"Result: Remapped {changes} Types. Failed to remap {failures} Types", ConsoleColor.Yellow);
Logger.Log("-----------------------------------------------", ConsoleColor.Yellow);
2024-06-11 19:18:48 -04:00
}
2024-06-13 01:53:43 -04:00
/// <summary>
/// Choose best match from a collection of scores, then start the renaming process
/// </summary>
/// <param name="scores">Scores to rate</param>
private void ChooseBestMatch(HashSet<ScoringModel> scores)
2024-06-11 19:18:48 -04:00
{
2024-06-13 01:46:51 -04:00
if (scores.Count == 0) { return; }
2024-06-11 19:18:48 -04:00
2024-06-12 19:42:16 -04:00
var highestScore = scores.OrderByDescending(score => score.Score).FirstOrDefault();
2024-06-11 19:18:48 -04:00
2024-06-11 23:07:59 -04:00
if (highestScore is null) { return; }
2024-06-11 19:18:48 -04:00
2024-06-11 23:07:59 -04:00
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
2024-06-12 00:05:59 -04:00
Logger.Log($"Renaming {highestScore.Definition.Name} to {highestScore.ProposedNewName}", ConsoleColor.Green);
2024-06-13 01:46:51 -04:00
Logger.Log($"Max possible score: {highestScore.ReMap.SearchParams.CalculateMaxScore()}", ConsoleColor.Green);
2024-06-12 15:47:11 -04:00
Logger.Log($"Scored: {highestScore.Score} points", ConsoleColor.Green);
if (scores.Count > 1)
{
2024-06-12 19:42:16 -04:00
Logger.Log($"Warning! There were {scores.Count - 1} possible matches. Considering adding more search parameters", ConsoleColor.Yellow);
2024-06-12 15:47:11 -04:00
2024-06-12 19:42:16 -04:00
foreach (var score in scores.OrderByDescending(score => score.Score).Skip(1))
2024-06-12 15:47:11 -04:00
{
Logger.Log($"{score.Definition.Name} - Score [{score.Score}]", ConsoleColor.Yellow);
}
}
2024-06-12 00:05:59 -04:00
2024-06-13 01:46:51 -04:00
highestScore.ReMap.OriginalTypeName = highestScore.Definition.Name;
2024-06-12 20:40:10 -04:00
2024-06-12 14:38:43 -04:00
// Rename type and all associated type members
2024-06-12 20:17:23 -04:00
Renamer.RenameAll(highestScore);
2024-06-11 19:18:48 -04:00
2024-06-11 23:07:59 -04:00
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
2024-06-11 19:18:48 -04:00
}
2024-06-13 01:53:43 -04:00
/// <summary>
/// Write the assembly back to disk and update the mapping file on disk
/// </summary>
2024-06-11 19:18:48 -04:00
private void WriteAssembly()
{
var filename = Path.GetFileNameWithoutExtension(DataProvider.AppSettings.AssemblyPath);
var strippedPath = Path.GetDirectoryName(filename);
filename = $"{filename}-Remapped.dll";
var remappedPath = Path.Combine(strippedPath, filename);
DataProvider.AssemblyDefinition.Write(remappedPath);
2024-06-12 20:40:10 -04:00
DataProvider.UpdateMapping();
2024-06-11 19:18:48 -04:00
2024-06-11 23:07:59 -04:00
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
Logger.Log($"Complete: Assembly written to `{remappedPath}`", ConsoleColor.Green);
2024-06-12 20:40:10 -04:00
Logger.Log("Original type names updated on mapping file.", ConsoleColor.Green);
2024-06-11 23:07:59 -04:00
Logger.Log("-----------------------------------------------", ConsoleColor.Green);
2024-06-11 19:18:48 -04:00
}
}