Better duplication prevention and nested support
This commit is contained in:
9 files changed
+101
-80
No files matched your search
@@ -3,5 +3,4 @@ obj/
|
||||
/packages/
|
||||
riderModule.iml
|
||||
/_ReSharper.Caches/
|
||||
work
|
||||
.idea
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Submodule Reactor.Greenhouse/Mappings updated: 216cbf4c94...b127276f6a.
@@ -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' ">
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in new issue
Block a user