CLI: Merge some options into --must-compile

This commit is contained in:
Katy Coe
2019-11-17 22:43:58 +01:00
parent 37c63608df
commit f0134e0d16
3 changed files with 22 additions and 30 deletions

View File

@@ -21,15 +21,12 @@ namespace Il2CppInspector
// Namespace prefixes whose contents should be skipped
public List<string> 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<CustomAttributeData>())
.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<string> 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<string, string>();
@@ -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));

View File

@@ -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) : "";

View File

@@ -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