Model: Handle generic methods and set DeclaringMethod
This commit is contained in:
@@ -24,12 +24,16 @@ namespace Il2CppInspector.Reflection
|
||||
// List of type usages that are initialized via pointers in the image
|
||||
public Dictionary<ulong, TypeInfo> TypesByVirtualAddress { get; } = new Dictionary<ulong, TypeInfo>();
|
||||
|
||||
// List of all methods ordered by their MethodDefinitionIndex
|
||||
public MethodBase[] MethodsByDefinitionIndex { get; }
|
||||
|
||||
// List of all types
|
||||
|
||||
public Il2CppModel(Il2CppInspector package) {
|
||||
Package = package;
|
||||
TypesByDefinitionIndex = new TypeInfo[package.TypeDefinitions.Length];
|
||||
TypesByUsageIndex = new TypeInfo[package.TypeUsages.Count];
|
||||
MethodsByDefinitionIndex = new MethodBase[package.Methods.Length];
|
||||
|
||||
// Create Assembly objects from Il2Cpp package
|
||||
for (var image = 0; image < package.Images.Length; image++)
|
||||
|
||||
@@ -22,11 +22,12 @@ namespace Il2CppInspector.Reflection
|
||||
// Information/flags about the method
|
||||
public MethodAttributes Attributes { get; protected set; }
|
||||
|
||||
// True if the type contains unresolved generic type parameters
|
||||
public bool ContainsGenericParameters => throw new NotImplementedException();
|
||||
// True if the method contains unresolved generic type parameters
|
||||
public bool ContainsGenericParameters { get; }
|
||||
|
||||
// TODO: Custom attribute stuff
|
||||
|
||||
public List<TypeInfo> GenericTypeParameters { get; } // System.Reflection.MethodInfo.GetGenericArguments()
|
||||
public List<ParameterInfo> DeclaredParameters { get; } = new List<ParameterInfo>();
|
||||
|
||||
public bool IsAbstract => (Attributes & MethodAttributes.Abstract) == MethodAttributes.Abstract;
|
||||
@@ -36,8 +37,8 @@ namespace Il2CppInspector.Reflection
|
||||
public bool IsFamilyAndAssembly => (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem;
|
||||
public bool IsFamilyOrAssembly => (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem;
|
||||
public bool IsFinal => (Attributes & MethodAttributes.Final) == MethodAttributes.Final;
|
||||
public bool IsGenericMethod => throw new NotImplementedException();
|
||||
public bool IsGenericMethodDefinition => throw new NotImplementedException();
|
||||
public bool IsGenericMethod { get; }
|
||||
public bool IsGenericMethodDefinition { get; }
|
||||
public bool IsHideBySig => (Attributes & MethodAttributes.HideBySig) == MethodAttributes.HideBySig;
|
||||
public bool IsPrivate => (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private;
|
||||
public bool IsPublic => (Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;
|
||||
@@ -59,6 +60,24 @@ namespace Il2CppInspector.Reflection
|
||||
// Find method pointer
|
||||
VirtualAddress = pkg.GetMethodPointer(Assembly.Module, Definition);
|
||||
|
||||
// Add to global method definition list
|
||||
Assembly.Model.MethodsByDefinitionIndex[Index] = this;
|
||||
|
||||
// Generic method definition?
|
||||
if (Definition.genericContainerIndex >= 0) {
|
||||
IsGenericMethod = true;
|
||||
IsGenericMethodDefinition = true; // TODO: Only if all of the parameters are unresolved generic type parameters
|
||||
ContainsGenericParameters = true;
|
||||
|
||||
// Store the generic type parameters for later instantiation
|
||||
var container = pkg.GenericContainers[Definition.genericContainerIndex];
|
||||
|
||||
GenericTypeParameters = pkg.GenericParameters.Skip((int)container.genericParameterStart).Take(container.type_argc).Select(p => new TypeInfo(this, p)).ToList();
|
||||
|
||||
// TODO: Constraints
|
||||
// TODO: Attributes
|
||||
}
|
||||
|
||||
// Set method attributes
|
||||
if ((Definition.flags & Il2CppConstants.METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == Il2CppConstants.METHOD_ATTRIBUTE_PRIVATE)
|
||||
Attributes |= MethodAttributes.Private;
|
||||
@@ -142,6 +161,9 @@ namespace Il2CppInspector.Reflection
|
||||
public string GetParametersString() =>
|
||||
string.Join(", ", DeclaredParameters.Select(p => $"{p.GetModifierString()}{p.ParameterType.CSharpName} {p.Name}"));
|
||||
|
||||
public string GetTypeParametersString() => GenericTypeParameters == null? "" :
|
||||
"<" + string.Join(", ", GenericTypeParameters.Select(p => p.CSharpName)) + ">";
|
||||
|
||||
// List of operator overload metadata names
|
||||
// https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/operator-overloads
|
||||
public static Dictionary<string, string> OperatorMethodNames = new Dictionary<string, string> {
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace Il2CppInspector.Reflection
|
||||
ReturnParameter = new ParameterInfo(pkg, -1, this);
|
||||
}
|
||||
|
||||
// TODO: Generic arguments (and on ConstructorInfo)
|
||||
public override string ToString() => ReturnType.Name + " " + Name + "(" + string.Join(", ", DeclaredParameters.Select(x => x.ParameterType.Name)) + ")";
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,11 @@ namespace Il2CppInspector.Reflection {
|
||||
// True if the type contains unresolved generic type parameters
|
||||
public bool ContainsGenericParameters { get; }
|
||||
|
||||
public string BaseName => base.Name;
|
||||
|
||||
// Get rid of generic backticks
|
||||
public string UnmangledBaseName => base.Name.IndexOf("`", StringComparison.Ordinal) == -1 ? base.Name : base.Name.Remove(base.Name.IndexOf("`", StringComparison.Ordinal));
|
||||
|
||||
// C# colloquial name of the type (if available)
|
||||
public string CSharpName {
|
||||
get {
|
||||
@@ -46,6 +51,14 @@ namespace Il2CppInspector.Reflection {
|
||||
}
|
||||
}
|
||||
|
||||
// C# name as it would be written in a type declaration
|
||||
public string CSharpTypeDeclarationName =>
|
||||
(IsPointer ? "void *" : "")
|
||||
+ (base.Name.IndexOf("`", StringComparison.Ordinal) == -1 ? base.Name : base.Name.Remove(base.Name.IndexOf("`", StringComparison.Ordinal)))
|
||||
+ (GenericTypeParameters != null ? "<" + string.Join(", ", GenericTypeParameters.Select(x => x.Name)) + ">" : "")
|
||||
+ (GenericTypeArguments != null ? "<" + string.Join(", ", GenericTypeArguments.Select(x => x.Name)) + ">" : "")
|
||||
+ (IsArray ? "[]" : "");
|
||||
|
||||
public List<ConstructorInfo> DeclaredConstructors { get; } = new List<ConstructorInfo>();
|
||||
public List<EventInfo> DeclaredEvents { get; } = new List<EventInfo>();
|
||||
public List<FieldInfo> DeclaredFields { get; } = new List<FieldInfo>();
|
||||
@@ -58,7 +71,9 @@ namespace Il2CppInspector.Reflection {
|
||||
public List<PropertyInfo> DeclaredProperties { get; } = new List<PropertyInfo>();
|
||||
|
||||
// Method that the type is declared in if this is a type parameter of a generic method
|
||||
public MethodBase DeclaringMethod => null; // TODO: Implement for methods
|
||||
public MethodBase DeclaringMethod;
|
||||
|
||||
// IsGenericTypeParameter and IsGenericMethodParameter from https://github.com/dotnet/corefx/issues/23883
|
||||
public bool IsGenericTypeParameter => IsGenericParameter && DeclaringMethod == null;
|
||||
public bool IsGenericMethodParameter => IsGenericParameter && DeclaringMethod != null;
|
||||
|
||||
@@ -127,17 +142,6 @@ namespace Il2CppInspector.Reflection {
|
||||
// May get overridden by Il2CppType-based constructor below
|
||||
public override MemberTypes MemberType { get; } = MemberTypes.TypeInfo;
|
||||
|
||||
public string BaseName => base.Name;
|
||||
|
||||
public override string Name {
|
||||
get => (IsPointer ? "void *" : "")
|
||||
+ (base.Name.IndexOf("`", StringComparison.Ordinal) == -1? base.Name : base.Name.Remove(base.Name.IndexOf("`", StringComparison.Ordinal)))
|
||||
+ (GenericTypeParameters != null? "<" + string.Join(", ", GenericTypeParameters.Select(x => x.Name)) + ">" : "")
|
||||
+ (GenericTypeArguments != null ? "<" + string.Join(", ", GenericTypeArguments.Select(x => x.Name)) + ">" : "")
|
||||
+ (IsArray ? "[]" : "");
|
||||
protected set => base.Name = value;
|
||||
}
|
||||
|
||||
private string @namespace;
|
||||
public string Namespace {
|
||||
get => !string.IsNullOrEmpty(@namespace) ? @namespace : DeclaringType?.Namespace ?? "";
|
||||
@@ -179,7 +183,7 @@ namespace Il2CppInspector.Reflection {
|
||||
MemberType |= MemberTypes.NestedType;
|
||||
}
|
||||
|
||||
// Generic type?
|
||||
// Generic type definition?
|
||||
if (Definition.genericContainerIndex >= 0) {
|
||||
IsGenericType = true;
|
||||
IsGenericParameter = false;
|
||||
@@ -358,6 +362,10 @@ namespace Il2CppInspector.Reflection {
|
||||
declaringTypeDefinitionIndex = ownerType.Index;
|
||||
MemberType = memberType | MemberTypes.NestedType;
|
||||
|
||||
// All generic method type parameters have a declared method
|
||||
if (container.is_method == 1)
|
||||
DeclaringMethod = model.MethodsByDefinitionIndex[container.ownerIndex];
|
||||
|
||||
IsGenericParameter = true;
|
||||
ContainsGenericParameters = true;
|
||||
IsGenericType = false;
|
||||
@@ -369,7 +377,7 @@ namespace Il2CppInspector.Reflection {
|
||||
IsPointer = (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_PTR);
|
||||
}
|
||||
|
||||
// Initialize a type that is a generic parameter
|
||||
// Initialize a type that is a generic parameter of a generic type
|
||||
// See: https://docs.microsoft.com/en-us/dotnet/api/system.type.isgenerictype?view=netframework-4.8
|
||||
public TypeInfo(TypeInfo declaringType, Il2CppGenericParameter param) : base(declaringType) {
|
||||
// Same visibility attributes as declaring type
|
||||
@@ -389,5 +397,10 @@ namespace Il2CppInspector.Reflection {
|
||||
IsGenericTypeDefinition = false;
|
||||
ContainsGenericParameters = true;
|
||||
}
|
||||
|
||||
// Initialize a type that is a generic parameter of a generic method
|
||||
public TypeInfo(MethodBase declaringMethod, Il2CppGenericParameter param) : this(declaringMethod.DeclaringType, param) {
|
||||
DeclaringMethod = declaringMethod;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user