Better duplication prevention and nested support

This commit is contained in:
js6pak committed 2021-01-15 23:07:22 +01:00
1 parent 79df790aec
commit 4a527d5cee
9 files changed
+101 -80

No files matched your search

-1
View File
@@ -3,5 +3,4 @@ obj/
/packages/
riderModule.iml
/_ReSharper.Caches/
work
.idea
+8 -4
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using Mono.Cecil;
using Mono.Cecil.Rocks;
using Reactor.OxygenFilter;
namespace Reactor.Greenhouse
@@ -115,7 +116,7 @@ namespace Reactor.Greenhouse
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 @@ namespace Reactor.Greenhouse
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 @@ namespace Reactor.Greenhouse
);
nested.Compile(nestedDef, mappings);
mappings.Types.Add(nested);
}
type.Nested.Clear();
foreach (var property in type.Properties)
{
try
@@ -180,11 +184,11 @@ namespace Reactor.Greenhouse
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);
}
+84 -61
View File
@@ -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<TypeDefinition, SortedList<double, TypeDefinition>>();
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<double, TypeDefinition>(Comparer<double>.Create((x, y) => y.CompareTo(x)));
matches[oldType] = list;
var exact = latest.GetAllTypes().FirstOrDefault(x => x.FullName == oldType.FullName);
if (exact != null)
{
var mapped = new MappedType(new OriginalDescriptor { Name = type.Name }, oldType.Name);
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 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 @@ namespace Reactor.Greenhouse
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;
}
}
+4 -4
View File
@@ -77,13 +77,13 @@ namespace Reactor.Greenhouse
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)
@@ -4,7 +4,7 @@
<LangVersion>latest</LangVersion>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<Version>0.2.2</Version>
<Version>0.2.3</Version>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/NuclearPowered/Reactor.OxygenFilter</RepositoryUrl>
<PackageLicenseExpression>LGPL-3.0-or-later</PackageLicenseExpression>
@@ -17,7 +17,7 @@
<ProjectReference Include="..\Reactor.OxygenFilter\Reactor.OxygenFilter.csproj" />
<PackageReference Include="js6pak.Il2CppDumper" Version="6.4.20" />
<PackageReference Include="NuclearPowered.AssemblyUnhollower" Version="0.4.12" />
<PackageReference Include="NuclearPowered.AssemblyUnhollower" Version="0.4.13" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net472' ">
+1 -1
View File
@@ -11,7 +11,7 @@ namespace Reactor.OxygenFilter
public MappedType Find(string name, Func<MappedType, string> predicate)
{
var split = name.Split('.').SelectMany(x => x.Split('+')).ToArray();
var split = name.Split('.', '+', '/').ToArray();
if (split.Length > 1)
{
@@ -143,11 +143,6 @@ namespace Reactor.OxygenFilter
}
}
}
foreach (var nested in type.Nested)
{
MapType(nested, typeDef.NestedTypes.SingleOrDefault(x => x.Name == nested.Original.Name));
}
}
foreach (var type in Mappings.Types)
@@ -3,7 +3,7 @@
<TargetFrameworks>net472;netstandard2.0</TargetFrameworks>
<LangVersion>latest</LangVersion>
<Version>0.1.0</Version>
<Version>0.1.1</Version>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/NuclearPowered/Reactor.OxygenFilter</RepositoryUrl>
<PackageLicenseExpression>LGPL-3.0-or-later</PackageLicenseExpression>