diff --git a/Il2CppDumper/Il2CppCSharpDumper.cs b/Il2CppDumper/Il2CppCSharpDumper.cs index 77efaa2..deda284 100644 --- a/Il2CppDumper/Il2CppCSharpDumper.cs +++ b/Il2CppDumper/Il2CppCSharpDumper.cs @@ -228,11 +228,11 @@ namespace Il2CppInspector if (field.GetCustomAttributes(FBAttribute).Any()) { if (!SuppressMetadata) sb.Append($"/* {field.GetCustomAttributes(FBAttribute)[0].VirtualAddress.ToAddressString()} */ "); - sb.Append($"{field.FieldType.DeclaredFields[0].FieldType.GetScopedCSharpName(scope)} {field.Name}[0]"); // FixedElementField + sb.Append($"{field.FieldType.DeclaredFields[0].FieldType.GetScopedCSharpName(scope)} {field.CSharpSafeName}[0]"); // FixedElementField } // Regular fields else - sb.Append($"{field.FieldType.GetScopedCSharpName(scope)} {field.Name}"); + sb.Append($"{field.FieldType.GetScopedCSharpName(scope)} {field.CSharpSafeName}"); if (field.HasDefaultValue) sb.Append($" = {field.DefaultValueString}"); sb.Append(";"); @@ -308,7 +308,7 @@ namespace Il2CppInspector .ToString(scope, prefix + "\t", emitPointer: !SuppressMetadata, mustCompile: MustCompile)); string modifiers = evt.AddMethod?.GetModifierString(); - sb.Append($"{prefix}\t{modifiers}event {evt.EventHandlerType.GetScopedCSharpName(scope)} {evt.Name}"); + sb.Append($"{prefix}\t{modifiers}event {evt.EventHandlerType.GetScopedCSharpName(scope)} {evt.CSharpSafeName}"); if (!MustCompile) { sb.Append(" {{\n"); diff --git a/Il2CppInspector/Reflection/Constants.cs b/Il2CppInspector/Reflection/Constants.cs new file mode 100644 index 0000000..a8a701a --- /dev/null +++ b/Il2CppInspector/Reflection/Constants.cs @@ -0,0 +1,40 @@ +/* + Copyright 2017-2019 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com + + All rights reserved. +*/ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Il2CppInspector.Reflection +{ + public static class Constants + { + // All C# reserved keywords + // From: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/ + public static readonly string[] Keywords = { + "abstract", "as", "base", "bool", + "break", "byte", "case", "catch", + "char", "checked", "class", "const", + "continue", "decimal", "default", "delegate", + "do", "double", "else", "enum", + "event", "explicit", "extern", "false", + "finally", "fixed", "float", "for", + "foreach", "goto", "if", "implicit", + "in", "int", "interface", "internal", + "is", "lock", "long", "namespace", + "new", "null", "object", "operator", + "out", "override", "params", "private", + "protected", "public", "readonly", "ref", + "return", "sbyte", "sealed", "short", + "sizeof", "stackalloc", "static", "string", + "struct", "switch", "this", "throw", + "true", "try", "typeof", "uint", + "ulong", "unchecked", "unsafe", "ushort", + "using", /* "using static", */ "virtual", "void", + "volatile", "while" + }; + } +} diff --git a/Il2CppInspector/Reflection/MemberInfo.cs b/Il2CppInspector/Reflection/MemberInfo.cs index e550efe..c2495c3 100644 --- a/Il2CppInspector/Reflection/MemberInfo.cs +++ b/Il2CppInspector/Reflection/MemberInfo.cs @@ -29,6 +29,9 @@ namespace Il2CppInspector.Reflection { // Name of the member public virtual string Name { get; protected set; } + // Name of the member with @ prepended if the name is a C# reserved keyword + public string CSharpSafeName => Constants.Keywords.Contains(Name) ? "@" + Name : Name; + // For top-level members in an assembly (ie. non-nested types) protected MemberInfo(Assembly asm) => Assembly = asm; diff --git a/Il2CppInspector/Reflection/ParameterInfo.cs b/Il2CppInspector/Reflection/ParameterInfo.cs index bc64db9..3755ead 100644 --- a/Il2CppInspector/Reflection/ParameterInfo.cs +++ b/Il2CppInspector/Reflection/ParameterInfo.cs @@ -40,6 +40,7 @@ namespace Il2CppInspector.Reflection // Name of parameter public string Name { get; } + public string CSharpSafeName => Constants.Keywords.Contains(Name) ? "@" + Name : Name; // Type of this parameter private readonly int paramTypeUsage; @@ -106,7 +107,7 @@ namespace Il2CppInspector.Reflection public string GetParameterString(Scope usingScope, bool emitPointer = false, bool compileAttributes = false) => IsRetval? null : (Position == 0 && DeclaringMethod.GetCustomAttributes("System.Runtime.CompilerServices.ExtensionAttribute").Any()? "this ":"") + $"{CustomAttributes.ToString(usingScope, inline: true, emitPointer: emitPointer, mustCompile: compileAttributes).Replace("[ParamArray]", "params")}" - + $"{getCSharpSignatureString(usingScope)} {Name}" + + $"{getCSharpSignatureString(usingScope)} {CSharpSafeName}" + (IsOptional? " = " + DefaultValue.ToCSharpValue(ParameterType, usingScope) + (emitPointer && !(DefaultValue is null)? $" /* Metadata: 0x{(uint) DefaultValueMetadataAddress:X8} */" : "") : ""); diff --git a/Il2CppInspector/Reflection/PropertyInfo.cs b/Il2CppInspector/Reflection/PropertyInfo.cs index 8c3e0a8..1d78c82 100644 --- a/Il2CppInspector/Reflection/PropertyInfo.cs +++ b/Il2CppInspector/Reflection/PropertyInfo.cs @@ -30,7 +30,7 @@ namespace Il2CppInspector.Reflection { public string CSharpName => // Explicit interface implementation - Name.IndexOf('.') != -1? string.Join('.', Name.Split('.')[^2..]) + CSharpSafeName.IndexOf('.') != -1? string.Join('.', CSharpSafeName.Split('.')[^2..]) // Regular method : Name; diff --git a/Il2CppInspector/Reflection/TypeInfo.cs b/Il2CppInspector/Reflection/TypeInfo.cs index 4c9f196..97f2cf1 100644 --- a/Il2CppInspector/Reflection/TypeInfo.cs +++ b/Il2CppInspector/Reflection/TypeInfo.cs @@ -544,6 +544,10 @@ namespace Il2CppInspector.Reflection { for (var p = Definition.propertyStart; p < Definition.propertyStart + Definition.property_count; p++) DeclaredProperties.Add(new PropertyInfo(pkg, p, this)); + // There are rare cases when properties are only given as methods in the metadata + // Find these and add them as properties + + // Add all events for (var e = Definition.eventStart; e < Definition.eventStart + Definition.event_count; e++) DeclaredEvents.Add(new EventInfo(pkg, e, this));