Files
gregExtractor/Services/DiffService.cs
T

83 lines
3.1 KiB
C#

using gregExtractor.Models;
namespace gregExtractor.Services;
public sealed class DiffService
{
public HookDiff Diff(List<HookDefinition> oldHooks, List<HookDefinition> newHooks)
{
oldHooks ??= new List<HookDefinition>();
newHooks ??= new List<HookDefinition>();
Dictionary<string, HookDefinition> oldMap = oldHooks
.GroupBy(GetKey)
.ToDictionary(group => group.Key, group => group.Last(), StringComparer.Ordinal);
Dictionary<string, HookDefinition> newMap = newHooks
.GroupBy(GetKey)
.ToDictionary(group => group.Key, group => group.Last(), StringComparer.Ordinal);
HookDefinition[] added = newMap
.Where(pair => !oldMap.ContainsKey(pair.Key))
.Select(pair => pair.Value)
.OrderBy(x => x.Group, StringComparer.OrdinalIgnoreCase)
.ThenBy(x => x.ClassName, StringComparer.OrdinalIgnoreCase)
.ThenBy(x => x.MethodName, StringComparer.OrdinalIgnoreCase)
.ToArray();
HookDefinition[] removed = oldMap
.Where(pair => !newMap.ContainsKey(pair.Key))
.Select(pair => pair.Value)
.OrderBy(x => x.Group, StringComparer.OrdinalIgnoreCase)
.ThenBy(x => x.ClassName, StringComparer.OrdinalIgnoreCase)
.ThenBy(x => x.MethodName, StringComparer.OrdinalIgnoreCase)
.ToArray();
HookDefinition[] changed = newMap
.Where(pair => oldMap.TryGetValue(pair.Key, out HookDefinition? oldHook) && HasSignatureChange(oldHook, pair.Value))
.Select(pair => pair.Value)
.OrderBy(x => x.Group, StringComparer.OrdinalIgnoreCase)
.ThenBy(x => x.ClassName, StringComparer.OrdinalIgnoreCase)
.ThenBy(x => x.MethodName, StringComparer.OrdinalIgnoreCase)
.ToArray();
return new HookDiff(added, removed, changed);
}
public static string GetKey(HookDefinition hook)
{
return Normalize($"{hook.Namespace}.{hook.ClassName}::{hook.MethodName}");
}
private static bool HasSignatureChange(HookDefinition oldHook, HookDefinition newHook)
{
if (!string.Equals(Normalize(oldHook.ReturnType), Normalize(newHook.ReturnType), StringComparison.Ordinal))
return true;
if (oldHook.Parameters.Count != newHook.Parameters.Count)
return true;
for (int i = 0; i < oldHook.Parameters.Count; i++)
{
HookParameter oldParameter = oldHook.Parameters[i];
HookParameter newParameter = newHook.Parameters[i];
if (!string.Equals(Normalize(oldParameter.Type), Normalize(newParameter.Type), StringComparison.Ordinal))
return true;
if (!string.Equals(Normalize(oldParameter.Name), Normalize(newParameter.Name), StringComparison.Ordinal))
return true;
}
return false;
}
private static string Normalize(string value)
{
return (value ?? string.Empty)
.Replace("global::", string.Empty)
.Replace(" ", string.Empty)
.Trim();
}
}