241 lines
7.8 KiB
C#
Raw Normal View History

using dnlib.DotNet;
2024-06-16 01:48:48 -04:00
using ReCodeIt.Models;
using ReCodeIt.Utils;
namespace ReCodeIt.ReMapper;
internal static class RenameHelper
{
2024-06-16 03:43:00 -04:00
private static List<string> TokensToMatch => DataProvider.Settings.AutoMapper.TokensToMatch;
2024-06-16 01:48:48 -04:00
/// <summary>
/// Only used by the manual remapper, should probably be removed
/// </summary>
/// <param name="module"></param>
/// <param name="remap"></param>
/// <param name="direct"></param>
public static void RenameAll(IEnumerable<TypeDef> types, RemapModel remap, bool direct = false)
2024-06-16 01:48:48 -04:00
{
// Rename all fields and properties first
2024-06-21 17:01:07 -04:00
if (DataProvider.Settings.Remapper.MappingSettings.RenameFields)
{
RenameAllFields(
remap.TypePrimeCandidate.Name.String,
remap.NewTypeName,
types);
2024-06-21 17:01:07 -04:00
}
if (DataProvider.Settings.Remapper.MappingSettings.RenameProperties)
{
RenameAllProperties(
remap.TypePrimeCandidate.Name.String,
remap.NewTypeName,
types);
2024-06-21 17:01:07 -04:00
}
2024-06-16 01:48:48 -04:00
2024-06-18 17:35:31 -04:00
if (!direct)
{
RenameType(types, remap);
2024-06-18 17:35:31 -04:00
}
2024-06-16 01:48:48 -04:00
Logger.Log($"{remap.TypePrimeCandidate.Name.String} Renamed.", ConsoleColor.Green);
2024-06-16 01:48:48 -04:00
}
/// <summary>
/// Only used by the manual remapper, should probably be removed
/// </summary>
/// <param name="module"></param>
/// <param name="remap"></param>
/// <param name="type"></param>
public static void RenameAllDirect(IEnumerable<TypeDef> types, RemapModel remap, TypeDef type)
2024-06-16 01:48:48 -04:00
{
RenameAll(types, remap, true);
2024-06-16 01:48:48 -04:00
}
/// <summary>
/// Rename all fields recursively, returns number of fields changed
/// </summary>
/// <param name="oldTypeName"></param>
/// <param name="newTypeName"></param>
/// <param name="typesToCheck"></param>
/// <returns></returns>
public static IEnumerable<TypeDef> RenameAllFields(
2024-06-16 01:48:48 -04:00
string oldTypeName,
string newTypeName,
IEnumerable<TypeDef> typesToCheck,
2024-06-16 01:48:48 -04:00
int overAllCount = 0)
{
foreach (var type in typesToCheck)
{
2024-06-16 03:43:00 -04:00
var fields = type.Fields
.Where(field => field.Name.IsFieldOrPropNameInList(TokensToMatch));
if (!fields.Any()) { continue; }
2024-06-16 01:48:48 -04:00
int fieldCount = 0;
2024-06-16 03:43:00 -04:00
foreach (var field in fields)
2024-06-16 01:48:48 -04:00
{
if (field.FieldType.TypeName == oldTypeName)
2024-06-16 01:48:48 -04:00
{
var newFieldName = GetNewFieldName(newTypeName, fieldCount);
2024-06-16 01:48:48 -04:00
2024-06-16 03:43:00 -04:00
// Dont need to do extra work
2024-06-16 01:48:48 -04:00
if (field.Name == newFieldName) { continue; }
Logger.Log($"Renaming field on type {type.Name} named `{field.Name}` with type `{field.FieldType.TypeName}` to `{newFieldName}`", ConsoleColor.Green);
var oldName = field.Name.ToString();
2024-06-16 01:48:48 -04:00
field.Name = newFieldName;
UpdateTypeFieldMemberRefs(type, field, oldName);
UpdateAllTypeFieldMemberRefs(typesToCheck, field, oldName);
2024-06-16 01:48:48 -04:00
fieldCount++;
overAllCount++;
}
}
}
2024-06-16 01:48:48 -04:00
return typesToCheck;
}
private static void UpdateAllTypeFieldMemberRefs(IEnumerable<TypeDef> typesToCheck, FieldDef newDef, string oldName)
{
foreach (var type in typesToCheck)
{
UpdateTypeFieldMemberRefs(type, newDef, oldName);
}
}
private static void UpdateTypeFieldMemberRefs(TypeDef type, FieldDef newDef, string oldName)
{
foreach (var method in type.Methods)
{
if (!method.HasBody) continue;
foreach (var instr in method.Body.Instructions)
2024-06-16 01:48:48 -04:00
{
if (instr.Operand is MemberRef memRef && memRef.Name == oldName)
{
//if (!memRef.Name.IsFieldOrPropNameInList(TokensToMatch)) continue;
Logger.Log($"Renaming MemRef in method {method.DeclaringType.Name}::{method.Name} from `{memRef.Name}` to `{newDef.Name}`", ConsoleColor.Yellow);
memRef.Name = newDef.Name;
}
2024-06-16 01:48:48 -04:00
}
}
}
2024-06-16 01:48:48 -04:00
private static void RenameAllFieldRefsInMethods(IEnumerable<TypeDef> typesToCheck, FieldDef newDef, string oldName)
{
foreach (var type in typesToCheck)
{
foreach (var method in type.Methods)
{
if (!method.HasBody) continue;
ChangeFieldNamesInMethods(method, newDef, oldName);
}
}
}
/// <summary>
/// Rename all field and member refs in a method
/// </summary>
/// <param name="method"></param>
/// <param name="newDef"></param>
/// <param name="oldName"></param>
private static void ChangeFieldNamesInMethods(MethodDef method, FieldDef newDef, string oldName)
{
foreach (var instr in method.Body.Instructions)
{
if (instr.Operand is FieldDef fieldDef && fieldDef.Name == oldName)
{
if (!fieldDef.Name.IsFieldOrPropNameInList(TokensToMatch)) continue;
Logger.Log($"Renaming fieldDef in method {method.Name} from `{fieldDef.Name}` to `{newDef.Name}`", ConsoleColor.Yellow);
fieldDef.Name = newDef.Name;
}
}
2024-06-16 01:48:48 -04:00
}
/// <summary>
/// Rename all properties recursively, returns number of fields changed
/// </summary>
/// <param name="oldTypeName"></param>
/// <param name="newTypeName"></param>
/// <param name="typesToCheck"></param>
/// <returns></returns>
public static int RenameAllProperties(
string oldTypeName,
string newTypeName,
IEnumerable<TypeDef> typesToCheck,
2024-06-16 01:48:48 -04:00
int overAllCount = 0)
{
foreach (var type in typesToCheck)
{
2024-06-16 03:43:00 -04:00
var properties = type.Properties
.Where(prop => prop.Name.IsFieldOrPropNameInList(TokensToMatch));
2024-06-16 01:48:48 -04:00
2024-06-16 03:43:00 -04:00
if (!properties.Any()) { continue; }
int propertyCount = 0;
foreach (var property in properties)
2024-06-16 01:48:48 -04:00
{
if (property.PropertySig.RetType.TypeName == oldTypeName)
2024-06-16 01:48:48 -04:00
{
2024-06-16 03:43:00 -04:00
var newPropertyName = GetNewPropertyName(newTypeName, propertyCount);
// Dont need to do extra work
if (property.Name == newPropertyName) { continue; }
2024-06-16 01:48:48 -04:00
Logger.Log($"Renaming property on type {type.Name} named `{property.Name}` with type `{property.PropertySig.RetType.TypeName}` to `{newPropertyName}`", ConsoleColor.Green);
property.Name = new UTF8String(newPropertyName);
2024-06-16 01:48:48 -04:00
propertyCount++;
overAllCount++;
}
}
}
return overAllCount;
}
public static string GetNewFieldName(string NewName, int fieldCount = 0)
2024-06-16 01:48:48 -04:00
{
string newFieldCount = fieldCount > 0 ? $"_{fieldCount}" : string.Empty;
return $"{char.ToLower(NewName[0])}{NewName[1..]}{newFieldCount}";
2024-06-16 01:48:48 -04:00
}
public static string GetNewPropertyName(string newName, int propertyCount = 0)
{
return propertyCount > 0 ? $"{newName}_{propertyCount}" : newName;
}
2024-06-18 17:35:31 -04:00
private static void RenameType(IEnumerable<TypeDef> typesToCheck, RemapModel remap)
2024-06-18 17:35:31 -04:00
{
foreach (var type in typesToCheck)
{
if (type.HasNestedTypes)
{
RenameType(type.NestedTypes, remap);
2024-06-18 17:35:31 -04:00
}
if (remap.TypePrimeCandidate.Name is null) { continue; }
2024-06-22 02:28:36 -04:00
if (remap.SearchParams.IsNested is true &&
type.IsNested && type.Name == remap.TypePrimeCandidate.Name)
2024-06-22 02:28:36 -04:00
{
type.Name = remap.NewTypeName;
2024-06-22 02:28:36 -04:00
}
2024-06-18 17:35:31 -04:00
if (type.FullName == remap.TypePrimeCandidate.Name)
2024-06-18 17:35:31 -04:00
{
type.Name = remap.NewTypeName;
2024-06-18 17:35:31 -04:00
}
}
}
2024-06-16 01:48:48 -04:00
}