83 lines
3.1 KiB
C#
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();
|
|
}
|
|
}
|