From f0134e0d164538d4a9ab89dbfa3d05dbefbe93c4 Mon Sep 17 00:00:00 2001 From: Katy Coe Date: Sun, 17 Nov 2019 22:43:58 +0100 Subject: [PATCH] CLI: Merge some options into --must-compile --- Il2CppDumper/Il2CppCSharpDumper.cs | 39 ++++++++++++++---------------- Il2CppDumper/Program.cs | 10 +++----- Il2CppTests/TestRunner.cs | 3 +-- 3 files changed, 22 insertions(+), 30 deletions(-) diff --git a/Il2CppDumper/Il2CppCSharpDumper.cs b/Il2CppDumper/Il2CppCSharpDumper.cs index 5ec955d..93f1bfa 100644 --- a/Il2CppDumper/Il2CppCSharpDumper.cs +++ b/Il2CppDumper/Il2CppCSharpDumper.cs @@ -21,15 +21,12 @@ namespace Il2CppInspector // Namespace prefixes whose contents should be skipped public List ExcludedNamespaces { get; set; } - // Suppress types, fields and methods with the CompilerGenerated attribute; suppress the attribute itself from property getters and setters - public bool SuppressGenerated { get; set; } + // Make adjustments to ensure that the generated code compiles + public bool MustCompile { get; set; } // Suppress binary metadata in code comments public bool SuppressMetadata { get; set; } - // Comment out custom attributes with non-optional constructor arguments - public bool CommentAttributes { get; set; } - private const string CGAttribute = "System.Runtime.CompilerServices.CompilerGeneratedAttribute"; private const string FBAttribute = "System.Runtime.CompilerServices.FixedBufferAttribute"; private const string ExtAttribute = "System.Runtime.CompilerServices.ExtensionAttribute"; @@ -188,7 +185,7 @@ namespace Il2CppInspector text.Append(asm.CustomAttributes.Where(a => a.AttributeType.FullName != ExtAttribute) .Except(excludedAttributes ?? new List()) .OrderBy(a => a.AttributeType.Name) - .ToString(new Scope { Current = null, Namespaces = namespaces }, attributePrefix: "assembly: ", emitPointer: !SuppressMetadata, mustCompile: CommentAttributes)); + .ToString(new Scope { Current = null, Namespaces = namespaces }, attributePrefix: "assembly: ", emitPointer: !SuppressMetadata, mustCompile: MustCompile)); if (asm.CustomAttributes.Any()) text.Append("\n"); } @@ -197,7 +194,7 @@ namespace Il2CppInspector private string generateType(TypeInfo type, IEnumerable namespaces, string prefix = "") { // Don't output compiler-generated types if desired - if (SuppressGenerated && type.GetCustomAttributes(CGAttribute).Any()) + if (MustCompile && type.GetCustomAttributes(CGAttribute).Any()) return string.Empty; var codeBlocks = new Dictionary(); @@ -213,7 +210,7 @@ namespace Il2CppInspector sb.Clear(); if (!type.IsEnum) { foreach (var field in type.DeclaredFields) { - if (SuppressGenerated && field.GetCustomAttributes(CGAttribute).Any()) + if (MustCompile && field.GetCustomAttributes(CGAttribute).Any()) continue; if (field.IsNotSerialized) @@ -221,7 +218,7 @@ namespace Il2CppInspector // Attributes sb.Append(field.CustomAttributes.Where(a => a.AttributeType.FullName != FBAttribute).OrderBy(a => a.AttributeType.Name) - .ToString(scope, prefix + "\t", emitPointer: !SuppressMetadata, mustCompile: CommentAttributes)); + .ToString(scope, prefix + "\t", emitPointer: !SuppressMetadata, mustCompile: MustCompile)); sb.Append(prefix + "\t"); sb.Append(field.GetModifierString()); @@ -253,7 +250,7 @@ namespace Il2CppInspector foreach (var prop in type.DeclaredProperties) { // Attributes sb.Append(prop.CustomAttributes.OrderBy(a => a.AttributeType.Name) - .ToString(scope, prefix + "\t", emitPointer: !SuppressMetadata, mustCompile: CommentAttributes)); + .ToString(scope, prefix + "\t", emitPointer: !SuppressMetadata, mustCompile: MustCompile)); // The access mask enum values go from 1 (private) to 6 (public) in order from most to least restrictive var getAccess = (prop.GetMethod?.Attributes ?? 0) & MethodAttributes.MemberAccessMask; @@ -268,13 +265,13 @@ namespace Il2CppInspector // Indexer else sb.Append("this[" + string.Join(", ", primary.DeclaredParameters.SkipLast(getAccess >= setAccess? 0 : 1) - .Select(p => p.GetParameterString(scope, !SuppressMetadata, CommentAttributes))) + "] { "); + .Select(p => p.GetParameterString(scope, !SuppressMetadata, MustCompile))) + "] { "); - sb.Append((prop.CanRead? prop.GetMethod.CustomAttributes.Where(a => !SuppressGenerated || a.AttributeType.FullName != CGAttribute) - .ToString(scope, inline: true, emitPointer: !SuppressMetadata, mustCompile: CommentAttributes) + sb.Append((prop.CanRead? prop.GetMethod.CustomAttributes.Where(a => !MustCompile || a.AttributeType.FullName != CGAttribute) + .ToString(scope, inline: true, emitPointer: !SuppressMetadata, mustCompile: MustCompile) + (getAccess < setAccess? prop.GetMethod.GetAccessModifierString() : "") + "get; " : "") - + (prop.CanWrite? prop.SetMethod.CustomAttributes.Where(a => !SuppressGenerated || a.AttributeType.FullName != CGAttribute) - .ToString(scope, inline: true, emitPointer: !SuppressMetadata, mustCompile: CommentAttributes) + + (prop.CanWrite? prop.SetMethod.CustomAttributes.Where(a => !MustCompile || a.AttributeType.FullName != CGAttribute) + .ToString(scope, inline: true, emitPointer: !SuppressMetadata, mustCompile: MustCompile) + (setAccess < getAccess? prop.SetMethod.GetAccessModifierString() : "") + "set; " : "") + "}"); if (!SuppressMetadata) { if ((prop.CanRead && prop.GetMethod.VirtualAddress != null) || (prop.CanWrite && prop.SetMethod.VirtualAddress != null)) @@ -294,7 +291,7 @@ namespace Il2CppInspector foreach (var evt in type.DeclaredEvents) { // Attributes sb.Append(evt.CustomAttributes.OrderBy(a => a.AttributeType.Name) - .ToString(scope, prefix + "\t", emitPointer: !SuppressMetadata, mustCompile: CommentAttributes)); + .ToString(scope, prefix + "\t", emitPointer: !SuppressMetadata, mustCompile: MustCompile)); string modifiers = evt.AddMethod?.GetModifierString(scope); sb.Append($"{prefix}\t{modifiers}event {evt.EventHandlerType.GetScopedCSharpName(scope)} {evt.Name} {{\n"); @@ -318,7 +315,7 @@ namespace Il2CppInspector foreach (var method in type.DeclaredConstructors) { // Attributes sb.Append(method.CustomAttributes.OrderBy(a => a.AttributeType.Name) - .ToString(scope, prefix + "\t", emitPointer: !SuppressMetadata, mustCompile: CommentAttributes)); + .ToString(scope, prefix + "\t", emitPointer: !SuppressMetadata, mustCompile: MustCompile)); sb.Append($"{prefix}\t{method.GetModifierString(scope)}{method.DeclaringType.UnmangledBaseName}{method.GetTypeParametersString(scope)}("); sb.Append(method.GetParametersString(scope, !SuppressMetadata) + ")" + (method.IsAbstract? ";" : @" {}")); @@ -346,7 +343,7 @@ namespace Il2CppInspector // TODO: DefaultMemberAttribute should be output if it is present and the type does not have an indexer, otherwise suppressed // See https://docs.microsoft.com/en-us/dotnet/api/system.reflection.defaultmemberattribute?view=netframework-4.8 sb.Append(type.CustomAttributes.Where(a => a.AttributeType.FullName != DMAttribute && a.AttributeType.FullName != ExtAttribute) - .OrderBy(a => a.AttributeType.Name).ToString(scope, prefix, emitPointer: !SuppressMetadata, mustCompile: CommentAttributes)); + .OrderBy(a => a.AttributeType.Name).ToString(scope, prefix, emitPointer: !SuppressMetadata, mustCompile: MustCompile)); // Roll-up multicast delegates to use the 'delegate' syntactic sugar if (type.IsClass && type.IsSealed && type.BaseType?.FullName == "System.MulticastDelegate") { @@ -354,7 +351,7 @@ namespace Il2CppInspector var del = type.GetMethod("Invoke"); // IL2CPP doesn't seem to retain return type attributes - //sb.Append(del.ReturnType.CustomAttributes.ToString(prefix, "return: ", emitPointer: !SuppressMetadata, mustCompile: CommentAttributes)); + //sb.Append(del.ReturnType.CustomAttributes.ToString(prefix, "return: ", emitPointer: !SuppressMetadata, mustCompile: MustCompile)); if (del.RequiresUnsafeContext) sb.Append("unsafe "); sb.Append($"delegate {del.ReturnType.GetScopedCSharpName(scope)} {type.CSharpTypeDeclarationName}("); @@ -403,14 +400,14 @@ namespace Il2CppInspector } private string generateMethod(MethodInfo method, Scope scope, string prefix) { - if (SuppressGenerated && method.GetCustomAttributes(CGAttribute).Any()) + if (MustCompile && method.GetCustomAttributes(CGAttribute).Any()) return string.Empty; var writer = new StringBuilder(); // Attributes writer.Append(method.CustomAttributes.Where(a => a.AttributeType.FullName != ExtAttribute).OrderBy(a => a.AttributeType.Name) - .ToString(scope, prefix + "\t", emitPointer: !SuppressMetadata, mustCompile: CommentAttributes)); + .ToString(scope, prefix + "\t", emitPointer: !SuppressMetadata, mustCompile: MustCompile)); // IL2CPP doesn't seem to retain return type attributes //writer.Append(method.ReturnType.CustomAttributes.ToString(prefix + "\t", "return: ", emitPointer: !SuppressMetadata)); diff --git a/Il2CppDumper/Program.cs b/Il2CppDumper/Program.cs index 8819b0f..a36fdda 100644 --- a/Il2CppDumper/Program.cs +++ b/Il2CppDumper/Program.cs @@ -49,11 +49,8 @@ namespace Il2CppInspector [Option('n', "suppress-metadata", Required = false, HelpText = "Diff tidying: suppress method pointers, field offsets and type indices from C# output. Useful for comparing two versions of a binary for changes with a diff tool", Default = false)] public bool SuppressMetadata { get; set; } - [Option('g', "suppress-cg", Required = false, HelpText = "Compilation tidying: Suppress generation of C# code for items with CompilerGenerated attribute", Default = false)] - public bool SuppressCompilerGenerated { get; set; } - - [Option('a', "comment-attributes", Required = false, HelpText = "Compilation tidying: comment out attributes without parameterless constructors or all-optional constructor arguments")] - public bool CommentParameterizedAttributeConstructors { get; set; } + [Option('k', "must-compile", Required = false, HelpText = "Compilation tidying: try really hard to make code that compiles. Suppress generation of code for items with CompilerGenerated attribute. Comment out attributes without parameterless constructors or all-optional constructor arguments")] + public bool MustCompile { get; set; } } public static int Main(string[] args) => @@ -90,9 +87,8 @@ namespace Il2CppInspector // C# signatures output var writer = new Il2CppCSharpDumper(model) { ExcludedNamespaces = options.ExcludedNamespaces.ToList(), - SuppressGenerated = options.SuppressCompilerGenerated, SuppressMetadata = options.SuppressMetadata, - CommentAttributes = options.CommentParameterizedAttributeConstructors + MustCompile = options.MustCompile }; var imageSuffix = i++ > 0 ? "-" + (i - 1) : ""; diff --git a/Il2CppTests/TestRunner.cs b/Il2CppTests/TestRunner.cs index f368d1a..474043f 100644 --- a/Il2CppTests/TestRunner.cs +++ b/Il2CppTests/TestRunner.cs @@ -56,9 +56,8 @@ namespace Il2CppInspector foreach (var il2cpp in inspectors) new Il2CppCSharpDumper(new Il2CppModel(il2cpp)) { ExcludedNamespaces = excludedNamespaces, - SuppressGenerated = true, SuppressMetadata = false, - CommentAttributes = true + MustCompile = true }.WriteSingleFile(testPath + @"\test-result" + (i++ > 0 ? "-" + (i - 1) : "") + ".cs"); // Compare test result with expected result