diff --git a/RecodeItLib/AutoMapper/ReCodeItAutoMapper.cs b/RecodeItLib/AutoMapper/ReCodeItAutoMapper.cs index dba793d..f3cbdd0 100644 --- a/RecodeItLib/AutoMapper/ReCodeItAutoMapper.cs +++ b/RecodeItLib/AutoMapper/ReCodeItAutoMapper.cs @@ -1,5 +1,7 @@ using Mono.Cecil; +using Mono.Collections.Generic; using ReCodeIt.Models; +using ReCodeIt.ReMapper; using ReCodeIt.Utils; using ReCodeItLib.Utils; @@ -16,6 +18,9 @@ public class ReCodeItAutoMapper private static bool Error { get; set; } = false; private int FailureCount { get; set; } = 0; + private int TotalFieldRenameCount { get; set; } = 0; + private int TotalPropertyRenameCount { get; set; } = 0; + /// /// Start the automapping process /// @@ -30,6 +35,8 @@ public class ReCodeItAutoMapper Error = false; FailureCount = 0; + TotalFieldRenameCount = 0; + TotalPropertyRenameCount = 0; FindCompilerGeneratedObjects(DataProvider.ModuleDefinition.Types); @@ -56,7 +63,7 @@ public class ReCodeItAutoMapper /// Finds any compiler generated code so we can ignore it, its mostly LINQ garbage /// /// - private void FindCompilerGeneratedObjects(Mono.Collections.Generic.Collection types) + private void FindCompilerGeneratedObjects(Collection types) { foreach (var typeDefinition in types) { @@ -117,12 +124,17 @@ public class ReCodeItAutoMapper { //Logger.Log($"Collecting Field: OriginalTypeRef: {field.FieldType.Name.TrimAfterSpecialChar()} Field Name: {field.Name}"); + var typeDef = field.FieldType.Resolve(); + + // Dont rename things we cant resolve + if (typeDef is null) { continue; } + fieldsWithTypes.Add(new MappingPair( - field.FieldType, + typeDef, field.Name, field.FieldType.Name.Contains("Interface"), field.FieldType.Name.Contains("Struct"), - field.FieldType.IsGenericInstance || field.FieldType.IsArray)); + field.IsPublic)); } return fieldsWithTypes; @@ -167,13 +179,17 @@ public class ReCodeItAutoMapper { //Logger.Log($"Collecting Property: OriginalTypeRef: {property.PropertyType.Name.TrimAfterSpecialChar()} Field Name: {property.Name}"); - ; + var typeDef = property.PropertyType.Resolve(); + + // Dont rename things we cant resolve + if (typeDef is null) { continue; } propertiesWithTypes.Add(new MappingPair( - property.PropertyType, + typeDef, property.Name, property.PropertyType.Name.Contains("Interface"), - property.PropertyType.Name.Contains("Struct"))); + property.PropertyType.Name.Contains("Struct"), + true)); } return propertiesWithTypes; @@ -194,7 +210,7 @@ public class ReCodeItAutoMapper // pair.OriginalTypeRef.Name is the property OriginalTypeRef name `Class1202` and token // is start identifer we are looking for `GClass` .Where(pair => Settings.TokensToMatch - .Any(token => pair.OriginalTypeRef.Name.StartsWith(token))) + .Any(token => pair.OriginalTypeDefinition.Name.StartsWith(token))) // Filter out anything that has the same name as the type, we cant remap those .Where(pair => !Settings.TokensToMatch @@ -210,7 +226,7 @@ public class ReCodeItAutoMapper .Where(pair => !pair.Name.ToCharArray().Contains('<')) // We only want types once, so make it unique - .GroupBy(pair => pair.OriginalTypeRef.FullName) + .GroupBy(pair => pair.OriginalTypeDefinition.FullName) .Select(group => group.First()) .GroupBy(pair => pair.Name) .Select(group => group.First()) @@ -245,7 +261,7 @@ public class ReCodeItAutoMapper { pair.Name = string.Concat("I", pair.Name.AsSpan(0)); } - + /* // Try and remove any trailing 's' that exist if (pair.WasCollection) { @@ -254,7 +270,7 @@ public class ReCodeItAutoMapper pair.Name = pair.Name.Substring(0, pair.Name.Length - 1); } } - + */ // If its not an interface, its a struct or class switch (pair.IsStruct) { @@ -268,9 +284,8 @@ public class ReCodeItAutoMapper } Logger.Log($"------------------------------------------------------------------------"); - Logger.Log($"Original Name: {pair.OriginalFullName} : Sanitized Name: {pair.Name}"); + Logger.Log($"Original Name: {pair.OriginalTypeDefinition.FullName} : Sanitized Name: {pair.Name}"); Logger.Log($"Matched From Name: {pair.OriginalPropOrFieldName}"); - Logger.Log($"Matched From Collection: {pair.WasCollection}"); Logger.Log($"IsInterface: {pair.IsInterface}"); Logger.Log($"IsStruct: {pair.IsStruct}"); Logger.Log($"------------------------------------------------------------------------"); @@ -284,6 +299,7 @@ public class ReCodeItAutoMapper /// private void StartRenameProcess() { + // Gather up any matches we have foreach (var type in DataProvider.ModuleDefinition.Types.ToArray()) { foreach (var pair in MappingPairs.ToArray()) @@ -292,17 +308,33 @@ public class ReCodeItAutoMapper } } + // Rename Types to matched types foreach (var pair in MappingPairs) { if (pair.NewTypeRef != null) { + Logger.Log($"------------------------------------------------------------------------", ConsoleColor.Green); + Logger.Log($"Renaming: {pair.OriginalTypeDefinition.Name} to {pair.Name}", ConsoleColor.Green); + + var fieldCount = RenameHelper.RenameAllFields( + pair.OriginalTypeDefinition.Name, + pair.Name, + DataProvider.ModuleDefinition.Types); + + var propCount = RenameHelper.RenameAllProperties( + pair.OriginalTypeDefinition.Name, + pair.Name, + DataProvider.ModuleDefinition.Types); + + TotalFieldRenameCount += fieldCount; + TotalPropertyRenameCount += propCount; + + Logger.Log($"Renamed: {fieldCount} fields", ConsoleColor.Green); + Logger.Log($"Renamed: {propCount} properties", ConsoleColor.Green); + Logger.Log($"------------------------------------------------------------------------", ConsoleColor.Green); + pair.NewTypeRef.Name = pair.Name; pair.HasBeenRenamed = true; - - Logger.Log($"------------------------------------------------------------------------", ConsoleColor.Green); - Logger.Log($"Renamed: {pair.OriginalShortName} to {pair.Name}", ConsoleColor.Green); - Logger.Log($"Original Full Name: {pair.OriginalFullName}", ConsoleColor.Green); - Logger.Log($"------------------------------------------------------------------------", ConsoleColor.Green); } } @@ -312,8 +344,7 @@ public class ReCodeItAutoMapper if (!pair.HasBeenRenamed) { Logger.Log($"------------------------------------------------------------------------", ConsoleColor.Red); - Logger.Log($"Renaming: {pair.OriginalTypeRef.Name} to {pair.Name} has failed", ConsoleColor.Red); - Logger.Log($"Matched From Collection: {pair.WasCollection}", ConsoleColor.Red); + Logger.Log($"Renaming: {pair.OriginalTypeDefinition.Name} to {pair.Name} has failed", ConsoleColor.Red); Logger.Log($"Trying to match: {pair.IsInterface}", ConsoleColor.Red); Logger.Log($"IsInterface: {pair.IsInterface}", ConsoleColor.Red); Logger.Log($"IsStruct: {pair.IsStruct}", ConsoleColor.Red); @@ -326,6 +357,8 @@ public class ReCodeItAutoMapper Logger.Log($"-------------------------------RESULT-----------------------------------", ConsoleColor.Yellow); Logger.Log($"Found {MappingPairs.Count()} automatic remaps", ConsoleColor.Yellow); + Logger.Log($"Renamed {TotalFieldRenameCount} fields", ConsoleColor.Yellow); + Logger.Log($"Renamed {TotalPropertyRenameCount} properties", ConsoleColor.Yellow); Logger.Log($"Failed to rename: {FailureCount} mapping pairs", ConsoleColor.Yellow); Logger.Log($"------------------------------------------------------------------------", ConsoleColor.Yellow); } @@ -343,7 +376,7 @@ public class ReCodeItAutoMapper GatherMatchedTypeRefs(pair, nestedType); } - if (type == pair.OriginalTypeRef || type.Name == pair.OriginalShortName && !pair.HasBeenRenamed) + if (type == pair.OriginalTypeDefinition) { pair.NewTypeRef = type; } @@ -361,31 +394,18 @@ public class ReCodeItAutoMapper /// /// private sealed class MappingPair( - TypeReference type, + TypeDefinition type, string name, - bool isInterface = false, - bool isStruct = false, - bool wasCollection = false) + bool isInterface, + bool isStruct, + bool isPublic) { - /// - /// The type reference for the field - /// - public TypeReference OriginalTypeRef { get; set; } = type; + public TypeDefinition OriginalTypeDefinition { get; private set; } = type; /// /// The type reference we want to change /// - public TypeReference NewTypeRef { get; set; } - - /// - /// The Original full name of the field type - /// - public string OriginalFullName { get; } = type.FullName; - - /// - /// Original short name of the type - /// - public string OriginalShortName { get; } = type.Name; + public TypeDefinition NewTypeRef { get; set; } /// /// Is this field an interface? @@ -397,11 +417,6 @@ public class ReCodeItAutoMapper /// public bool IsStruct { get; set; } = isStruct; - /// - /// Was this field a collection? - /// - public bool WasCollection { get; set; } = wasCollection; - /// /// Has this type been renamed? Use for checking for failures at the end /// diff --git a/RecodeItLib/Remapper/ReCodeItRemapper.cs b/RecodeItLib/Remapper/ReCodeItRemapper.cs index 52059d8..4028cd9 100644 --- a/RecodeItLib/Remapper/ReCodeItRemapper.cs +++ b/RecodeItLib/Remapper/ReCodeItRemapper.cs @@ -156,7 +156,7 @@ public class ReCodeItRemapper Logger.Log("-----------------------------------------------", ConsoleColor.Green); Logger.Log($"Renamed {oldName} to {type.Name} directly", ConsoleColor.Green); - Renamer.RenameAllDirect(remap, type); + RenameHelper.RenameAllDirect(remap, type); Logger.Log("-----------------------------------------------", ConsoleColor.Green); } @@ -226,7 +226,7 @@ public class ReCodeItRemapper highestScore.ReMap.OriginalTypeName = highestScore.Definition.Name; // Rename type and all associated type members - Renamer.RenameAll(highestScore); + RenameHelper.RenameAll(highestScore); Logger.Log("-----------------------------------------------", ConsoleColor.Green); } diff --git a/RecodeItLib/Remapper/RenameHelper.cs b/RecodeItLib/Remapper/RenameHelper.cs new file mode 100644 index 0000000..275bff0 --- /dev/null +++ b/RecodeItLib/Remapper/RenameHelper.cs @@ -0,0 +1,133 @@ +using Mono.Cecil; +using Mono.Collections.Generic; +using ReCodeIt.Models; +using ReCodeIt.Utils; + +namespace ReCodeIt.ReMapper; + +internal static class RenameHelper +{ + /// + /// Only used by the manual remapper, should probably be removed + /// + /// + public static void RenameAll(ScoringModel score) + { + var types = DataProvider.ModuleDefinition.Types; + + // Rename all fields and properties first + RenameAllFields(score.Definition.Name, score.ReMap.NewTypeName, types); + RenameAllProperties(score.Definition.Name, score.ReMap.NewTypeName, types); + + score.Definition.Name = score.ProposedNewName; + + Logger.Log($"{score.Definition.Name} Renamed.", ConsoleColor.Green); + } + + /// + /// Only used by the manual remapper, should probably be removed + /// + /// + public static void RenameAllDirect(RemapModel remap, TypeDefinition type) + { + var directRename = new ScoringModel(); + directRename.Definition = type; + directRename.ReMap = remap; + + RenameAll(directRename); + } + + /// + /// Rename all fields recursively, returns number of fields changed + /// + /// + /// + /// + /// + public static int RenameAllFields( + string oldTypeName, + string newTypeName, + Collection typesToCheck, + int overAllCount = 0) + { + foreach (var type in typesToCheck) + { + int fieldCount = 0; + foreach (var field in type.Fields) + { + if (field.FieldType.Name == oldTypeName) + { + var newFieldName = GetNewFieldName(newTypeName, field.IsPrivate, fieldCount); + + if (field.Name == newFieldName) { continue; } + + Logger.Log($"Renaming original field type name: `{field.FieldType.Name}` with name `{field.Name}` to `{newFieldName}`", ConsoleColor.Green); + + field.Name = newFieldName; + + fieldCount++; + overAllCount++; + } + } + + if (type.HasNestedTypes) + { + RenameAllFields(oldTypeName, newTypeName, type.NestedTypes, overAllCount); + } + } + + return overAllCount; + } + + /// + /// Rename all properties recursively, returns number of fields changed + /// + /// + /// + /// + /// + public static int RenameAllProperties( + string oldTypeName, + string newTypeName, + Collection typesToCheck, + int overAllCount = 0) + { + foreach (var type in typesToCheck) + { + int propertyCount = 0; + + foreach (var property in type.Properties) + { + if (property.PropertyType.Name == oldTypeName) + { + var newName = GetNewPropertyName(newTypeName, propertyCount); + + Logger.Log($"Renaming original property type name: `{property.PropertyType.Name}` with name `{property.Name}` to `{newName}`", ConsoleColor.Green); + property.Name = newName; + propertyCount++; + overAllCount++; + } + } + + if (type.HasNestedTypes) + { + RenameAllProperties(oldTypeName, newTypeName, type.NestedTypes, overAllCount); + } + } + + return overAllCount; + } + + public static string GetNewFieldName(string NewName, bool isPrivate, int fieldCount = 0) + { + var discard = isPrivate ? "_" : ""; + string newFieldCount = fieldCount > 0 ? $"_{fieldCount}" : string.Empty; + + return $"{discard}{char.ToLower(NewName[0])}{NewName[1..]}{newFieldCount}"; + } + + public static string GetNewPropertyName(string newName, int propertyCount = 0) + { + return propertyCount > 0 ? $"{newName}_{propertyCount}" : newName; + } +} \ No newline at end of file diff --git a/RecodeItLib/Remapper/Renamer.cs b/RecodeItLib/Remapper/Renamer.cs deleted file mode 100644 index 8056179..0000000 --- a/RecodeItLib/Remapper/Renamer.cs +++ /dev/null @@ -1,103 +0,0 @@ -using Mono.Cecil; -using Mono.Collections.Generic; -using ReCodeIt.Models; -using ReCodeIt.Utils; - -namespace ReCodeIt.ReMapper; - -internal static class Renamer -{ - public static void RenameAll(ScoringModel score) - { - var types = DataProvider.ModuleDefinition.Types; - - // Rename all fields and properties first - RenameAllFields(score, types); - RenameAllProperties(score, types); - - score.Definition.Name = score.ProposedNewName; - } - - public static void RenameAll() - { - } - - public static void RenameAllDirect(RemapModel remap, TypeDefinition type) - { - var directRename = new ScoringModel(); - directRename.Definition = type; - directRename.ReMap = remap; - - RenameAll(directRename); - } - - private static void RenameAllFields( - ScoringModel score, - Collection typesToCheck) - { - foreach (var type in typesToCheck) - { - int fieldCount = 0; - foreach (var field in type.Fields) - { - if (field.FieldType.Name == score.Definition.Name) - { - var newFieldName = GetNewFieldName(score.ReMap.NewTypeName, field.IsPrivate, fieldCount); - - if (field.Name == newFieldName) { continue; } - - Logger.Log($"Renaming field: `{field.Name}` on OriginalTypeRef `{type.Name}` to {newFieldName}", ConsoleColor.Green); - - field.Name = newFieldName; - - fieldCount++; - } - } - - if (type.HasNestedTypes) - { - foreach (var _ in type.NestedTypes) - { - RenameAllFields(score, type.NestedTypes); - } - } - } - } - - private static void RenameAllProperties( - ScoringModel score, - Collection typesToCheck) - { - foreach (var type in typesToCheck) - { - int propertyCount = 0; - - foreach (var property in type.Properties) - { - if (property.PropertyType.Name == score.Definition.Name) - { - var newName = propertyCount > 0 ? $"{score.ReMap.NewTypeName}_{propertyCount}" : score.ReMap.NewTypeName; - - Logger.Log($"Renaming Property: `{property.Name}` on OriginalTypeRef `{type}` to {newName}", ConsoleColor.Green); - property.Name = newName; - } - } - - if (type.HasNestedTypes) - { - foreach (var _ in type.NestedTypes) - { - RenameAllProperties(score, type.NestedTypes); - } - } - } - } - - private static string GetNewFieldName(string TypeName, bool isPrivate, int fieldCount = 0) - { - var discard = isPrivate ? "_" : ""; - string newFieldCount = fieldCount > 0 ? $"_{fieldCount}" : string.Empty; - - return $"{discard}{char.ToLower(TypeName[0])}{TypeName[1..]}{newFieldCount}"; - } -} \ No newline at end of file