From 4a527d5ceee66ffbb9ff6766cb3ee0cb7a16ca84 Mon Sep 17 00:00:00 2001 From: js6pak Date: Fri, 15 Jan 2021 23:07:22 +0100 Subject: [PATCH] Better duplication prevention and nested support --- .gitignore | 1 - Reactor.Greenhouse/Compiler.cs | 12 +- Reactor.Greenhouse/Generator.cs | 145 ++++++++++-------- Reactor.Greenhouse/Mappings | 2 +- Reactor.Greenhouse/Program.cs | 8 +- .../Reactor.OxygenFilter.MSBuild.csproj | 4 +- Reactor.OxygenFilter/Mappings.cs | 2 +- Reactor.OxygenFilter/ObfuscationMapper.cs | 5 - .../Reactor.OxygenFilter.csproj | 2 +- 9 files changed, 101 insertions(+), 80 deletions(-) diff --git a/.gitignore b/.gitignore index cfae9ab..91953df 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,4 @@ obj/ /packages/ riderModule.iml /_ReSharper.Caches/ -work .idea \ No newline at end of file diff --git a/Reactor.Greenhouse/Compiler.cs b/Reactor.Greenhouse/Compiler.cs index 9d31da4..be4960d 100644 --- a/Reactor.Greenhouse/Compiler.cs +++ b/Reactor.Greenhouse/Compiler.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Text.RegularExpressions; using Mono.Cecil; +using Mono.Cecil.Rocks; using Reactor.OxygenFilter; namespace Reactor.Greenhouse @@ -115,7 +116,7 @@ private static bool TestProperty(MappedMember property, TypeDefinition typeDef, private static bool TestType(MappedType type, TypeDefinition typeDef, Mappings mappings) { - return (type.Original.Name == null || type.Original.Name == typeDef.Name) && + return (type.Original.Name == null || type.Original.Name == typeDef.FullName) && type.Methods.All(method => typeDef.Methods.Any(m => TestMethod(method, typeDef, m, mappings))) && type.Fields.All(field => typeDef.Fields.Any(f => TestField(field, typeDef, f, mappings))) && type.Properties.All(property => typeDef.Properties.Any(p => TestProperty(property, typeDef, p, mappings))); @@ -123,7 +124,7 @@ private static bool TestType(MappedType type, TypeDefinition typeDef, Mappings m private static void Compile(this MappedType type, TypeDefinition typeDef, Mappings mappings) { - type.Original = new OriginalDescriptor { Name = typeDef.Name }; + type.Original = new OriginalDescriptor { Name = typeDef.FullName }; foreach (var nested in type.Nested) { @@ -133,8 +134,11 @@ private static void Compile(this MappedType type, TypeDefinition typeDef, Mappin ); nested.Compile(nestedDef, mappings); + mappings.Types.Add(nested); } + type.Nested.Clear(); + foreach (var property in type.Properties) { try @@ -180,11 +184,11 @@ private static void Compile(this MappedType type, TypeDefinition typeDef, Mappin public static void Compile(this Mappings mappings, ModuleDefinition moduleDef) { - foreach (var type in mappings.Types) + foreach (var type in mappings.Types.ToList()) { try { - var typeDef = moduleDef.Types.Single(t => TestType(type, t, mappings)); + var typeDef = moduleDef.GetAllTypes().Single(t => TestType(type, t, mappings)); type.Compile(typeDef, mappings); } diff --git a/Reactor.Greenhouse/Generator.cs b/Reactor.Greenhouse/Generator.cs index e3ffde1..5408642 100644 --- a/Reactor.Greenhouse/Generator.cs +++ b/Reactor.Greenhouse/Generator.cs @@ -1,23 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using Mono.Cecil; +using Mono.Cecil.Rocks; using Reactor.OxygenFilter; namespace Reactor.Greenhouse { public static class Generator { + private static TypeAttributes IgnoreVisibility(this TypeAttributes typeAttributes) + { + return typeAttributes & ~TypeAttributes.VisibilityMask; + } + public static Mappings Generate(ModuleDefinition old, ModuleDefinition latest) { + var matches = new Dictionary>(); + var result = new Mappings(); - foreach (var oldType in old.Types) + foreach (var oldType in old.GetAllTypes()) { if (oldType.Name.StartsWith("<") || oldType.Namespace.StartsWith("GoogleMobileAds")) continue; - void AddType(TypeDefinition type) + var list = new SortedList(Comparer.Create((x, y) => y.CompareTo(x))); + matches[oldType] = list; + + var exact = latest.GetAllTypes().FirstOrDefault(x => x.FullName == oldType.FullName); + if (exact != null) + { + list.Add(double.MaxValue, exact); + continue; + } + + if (oldType.IsEnum) + { + var first = oldType.Fields.Select(x => x.Name).ToArray(); + var type = latest.GetAllTypes().SingleOrDefault(x => x.IsEnum && x.Fields.Select(f => f.Name).SequenceEqual(first)); + if (type != null) + { + list.Add(double.MaxValue, type); + } + + continue; + } + + static bool Test(TypeReference typeReference) + { + return typeReference.IsGenericParameter || typeReference.Namespace != string.Empty || !typeReference.Name.IsObfuscated(); + } + + var methodNames = oldType.GetMethods().Select(x => x.Name).ToArray(); + var fieldNames = oldType.Fields.Select(x => x.Name).ToArray(); + var propertyNames = oldType.Properties.Select(x => x.Name).ToArray(); + + var methodSignatures = oldType.GetMethods().Where(x => Test(x.ReturnType) && x.Parameters.All(p => Test(p.ParameterType))).Select(x => x.GetSignature()).ToArray(); + var fieldSignatures = oldType.Fields.Where(x => Test(x.FieldType) && (!x.FieldType.HasGenericParameters || x.FieldType.GenericParameters.All(Test))).Select(x => x.GetSignature()).ToArray(); + + var types = latest.GetAllTypes() + .Where(t => t.Attributes.IgnoreVisibility() == oldType.Attributes.IgnoreVisibility()) + .ToArray(); + + foreach (var t in types) { - var mapped = new MappedType(new OriginalDescriptor { Name = type.Name }, oldType.Name); + var points = 0d; + points += t.GetMethods().Count(m => !m.Name.IsObfuscated() && methodNames.Contains(m.Name)); + points += t.Fields.Count(f => !f.Name.IsObfuscated() && fieldNames.Contains(f.Name)) * 2d; + points += t.Properties.Count(p => propertyNames.Contains((p.GetMethod?.Name ?? p.SetMethod.Name).Substring(4))) * 2d; + + var fieldSignaturesPoints = fieldSignatures.Count(s => t.Fields.Any(f => f.GetSignature().ToString() == s.ToString())); + points += Math.Max(0, fieldSignaturesPoints - Math.Abs(t.Fields.Count - fieldSignaturesPoints)) / 2d; + + var methodSignaturesPoints = methodSignatures.Count(s => t.GetMethods().Any(m => m.GetSignature().ToString() == s.ToString())); + points += Math.Max(0, methodSignaturesPoints - Math.Abs(t.GetMethods().Count() - methodSignaturesPoints) / 2d) / 2d; + + if (points != 0) + { + list.TryAdd(points, t); + } + } + } + + foreach (var (oldType, list) in matches) + { + foreach (var (points, type) in list) + { + if (matches.Where(x => x.Key != oldType).SelectMany(x => x.Value).Any(x => x.Value == type && x.Key > points)) + { + continue; + } + + list.Clear(); + list.Add(double.MaxValue, type); + + var mapped = new MappedType(new OriginalDescriptor { Name = type.FullName }, oldType.Name); var i = 0; foreach (var field in type.Fields) @@ -67,68 +146,12 @@ void AddType(TypeDefinition type) if (type.Name == oldType.Name || (!type.Name.IsObfuscated() && !mapped.Fields.Any() && !mapped.Methods.Any())) { - return; + break; } result.Types.Add(mapped); - } - - var exact = latest.Types.FirstOrDefault(x => x.FullName == oldType.FullName); - if (exact != null) - { - AddType(exact); - continue; - } - - if (oldType.IsEnum) - { - var first = oldType.Fields.Select(x => x.Name).ToArray(); - var type = latest.Types.SingleOrDefault(x => x.IsEnum && x.Fields.Select(f => f.Name).SequenceEqual(first)); - if (type != null) - { - AddType(type); - } - - continue; - } - static bool Test(TypeReference typeReference) - { - return typeReference.IsGenericParameter || typeReference.Namespace != string.Empty || !typeReference.Name.IsObfuscated(); - } - - var methods = oldType.Methods.Where(x => Test(x.ReturnType) && x.Parameters.All(p => Test(p.ParameterType))).Select(x => x.GetSignature()).ToArray(); - var fields = oldType.Fields.Where(x => Test(x.FieldType) && (!x.FieldType.HasGenericParameters || x.FieldType.GenericParameters.All(Test))).Select(x => x.GetSignature()).ToArray(); - var properties = oldType.Properties.Select(x => x.Name).ToArray(); - - var types = latest.Types - .Where(t => t.Attributes == oldType.Attributes) - .ToArray(); - - TypeDefinition winner = null; - var winnerPoints = -1; - - foreach (var t in types) - { - var points = 0; - points += t.Properties.Count(p => properties.Contains((p.GetMethod?.Name ?? p.SetMethod.Name).Substring(4))); - points += fields.Count(s => t.Fields.Any(f => f.GetSignature().ToString() == s.ToString())); - points += methods.Count(s => t.Methods.Any(m => m.GetSignature().ToString() == s.ToString())); - - if (points > winnerPoints) - { - winnerPoints = points; - winner = t; - } - else if (points == winnerPoints) - { - winner = null; - } - } - - if (winner != null && winnerPoints > 0) - { - AddType(winner); + break; } } diff --git a/Reactor.Greenhouse/Mappings b/Reactor.Greenhouse/Mappings index 216cbf4..b127276 160000 --- a/Reactor.Greenhouse/Mappings +++ b/Reactor.Greenhouse/Mappings @@ -1 +1 @@ -Subproject commit 216cbf4c946b5ab10ef12b9cca39af72d2394496 +Subproject commit b127276f6a67d9ecbcdbddaa57935734d780e15b diff --git a/Reactor.Greenhouse/Program.cs b/Reactor.Greenhouse/Program.cs index 616d7e4..8f4061b 100644 --- a/Reactor.Greenhouse/Program.cs +++ b/Reactor.Greenhouse/Program.cs @@ -77,13 +77,13 @@ private static async Task GenerateAsync(Game game, ModuleDefinition old) await File.WriteAllTextAsync(Path.Combine("work", version + postfix + ".generated.json"), JsonConvert.SerializeObject(generated, Formatting.Indented)); - Apply(generated, Path.Combine("Mappings", "universal.json")); - Apply(generated, Path.Combine("Mappings", version + postfix + ".json")); + Apply(generated, Path.Combine("universal.json")); + Apply(generated, Path.Combine(version + postfix + ".json")); generated.Compile(moduleDef); - Directory.CreateDirectory(Path.Combine("Mappings", "bin")); - await File.WriteAllTextAsync(Path.Combine("Mappings", "bin", game.Name.ToLower() + ".json"), JsonConvert.SerializeObject(generated)); + Directory.CreateDirectory(Path.Combine("bin")); + await File.WriteAllTextAsync(Path.Combine("bin", game.Name.ToLower() + ".json"), JsonConvert.SerializeObject(generated)); } private static void Apply(Mappings generated, string file) diff --git a/Reactor.OxygenFilter.MSBuild/Reactor.OxygenFilter.MSBuild.csproj b/Reactor.OxygenFilter.MSBuild/Reactor.OxygenFilter.MSBuild.csproj index be440d2..6658216 100644 --- a/Reactor.OxygenFilter.MSBuild/Reactor.OxygenFilter.MSBuild.csproj +++ b/Reactor.OxygenFilter.MSBuild/Reactor.OxygenFilter.MSBuild.csproj @@ -4,7 +4,7 @@ latest true - 0.2.2 + 0.2.3 git https://github.com/NuclearPowered/Reactor.OxygenFilter LGPL-3.0-or-later @@ -17,7 +17,7 @@ - + diff --git a/Reactor.OxygenFilter/Mappings.cs b/Reactor.OxygenFilter/Mappings.cs index 5282e9d..0b96eba 100644 --- a/Reactor.OxygenFilter/Mappings.cs +++ b/Reactor.OxygenFilter/Mappings.cs @@ -11,7 +11,7 @@ public class Mappings public MappedType Find(string name, Func predicate) { - var split = name.Split('.').SelectMany(x => x.Split('+')).ToArray(); + var split = name.Split('.', '+', '/').ToArray(); if (split.Length > 1) { diff --git a/Reactor.OxygenFilter/ObfuscationMapper.cs b/Reactor.OxygenFilter/ObfuscationMapper.cs index dc9bc93..26ca27e 100644 --- a/Reactor.OxygenFilter/ObfuscationMapper.cs +++ b/Reactor.OxygenFilter/ObfuscationMapper.cs @@ -143,11 +143,6 @@ void MapType(MappedType type, TypeDefinition typeDef) } } } - - foreach (var nested in type.Nested) - { - MapType(nested, typeDef.NestedTypes.SingleOrDefault(x => x.Name == nested.Original.Name)); - } } foreach (var type in Mappings.Types) diff --git a/Reactor.OxygenFilter/Reactor.OxygenFilter.csproj b/Reactor.OxygenFilter/Reactor.OxygenFilter.csproj index b050d6f..c4cfd74 100644 --- a/Reactor.OxygenFilter/Reactor.OxygenFilter.csproj +++ b/Reactor.OxygenFilter/Reactor.OxygenFilter.csproj @@ -3,7 +3,7 @@ net472;netstandard2.0 latest - 0.1.0 + 0.1.1 git https://github.com/NuclearPowered/Reactor.OxygenFilter LGPL-3.0-or-later