Model: Handle generic type arguments in generic type declarations

This commit is contained in:
Katy Coe
2019-11-01 16:37:36 +01:00
parent 05bcf98dd3
commit 364daf9dd8
3 changed files with 25 additions and 11 deletions

View File

@@ -41,7 +41,7 @@ namespace Il2CppInspector.Reflection
case Il2CppTypeEnum.IL2CPP_TYPE_CLASS: case Il2CppTypeEnum.IL2CPP_TYPE_CLASS:
case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE: case Il2CppTypeEnum.IL2CPP_TYPE_VALUETYPE:
// Classes defined in the metadata // Classes defined in the metadata
return TypesByDefinitionIndex[usage.datapoint]; return TypesByDefinitionIndex[usage.datapoint]; // klassIndex
case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST: case Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST:
case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY: case Il2CppTypeEnum.IL2CPP_TYPE_ARRAY:

View File

@@ -12,7 +12,7 @@ namespace Il2CppInspector.Reflection {
public abstract class MemberInfo public abstract class MemberInfo
{ {
// Assembly that this member is defined in. Only set when MemberType == TypeInfo // Assembly that this member is defined in. Only set when MemberType == TypeInfo
public Assembly Assembly { get; } public Assembly Assembly { get; protected set; }
// Custom attributes for this member // Custom attributes for this member
public IEnumerable<CustomAttributeData> CustomAttributes => throw new NotImplementedException(); public IEnumerable<CustomAttributeData> CustomAttributes => throw new NotImplementedException();

View File

@@ -14,7 +14,7 @@ namespace Il2CppInspector.Reflection {
{ {
// IL2CPP-specific data // IL2CPP-specific data
public Il2CppTypeDefinition Definition { get; } public Il2CppTypeDefinition Definition { get; }
public int Index { get; } public int Index { get; } = -1;
// Information/flags about the type // Information/flags about the type
// Undefined if the Type represents a generic type parameter // Undefined if the Type represents a generic type parameter
@@ -41,6 +41,7 @@ namespace Il2CppInspector.Reflection {
if (IsArray) if (IsArray)
n = ElementType.CSharpName; n = ElementType.CSharpName;
var g = (GenericTypeParameters != null ? "<" + string.Join(", ", GenericTypeParameters.Select(x => x.CSharpName)) + ">" : ""); var g = (GenericTypeParameters != null ? "<" + string.Join(", ", GenericTypeParameters.Select(x => x.CSharpName)) + ">" : "");
g = (GenericTypeArguments != null ? "<" + string.Join(", ", GenericTypeArguments.Select(x => x.CSharpName)) + ">" : g);
return (IsPointer ? "void *" : "") + n + g + (IsArray ? "[]" : ""); return (IsPointer ? "void *" : "") + n + g + (IsArray ? "[]" : "");
} }
} }
@@ -82,6 +83,7 @@ namespace Il2CppInspector.Reflection {
+ (DeclaringType != null? DeclaringType.Name + "." : "") + (DeclaringType != null? DeclaringType.Name + "." : "")
+ base.Name + base.Name
+ (GenericTypeParameters != null ? "<" + string.Join(", ", GenericTypeParameters.Select(x => x.Name)) + ">" : "") + (GenericTypeParameters != null ? "<" + string.Join(", ", GenericTypeParameters.Select(x => x.Name)) + ">" : "")
+ (GenericTypeArguments != null ? "<" + string.Join(", ", GenericTypeArguments.Select(x => x.Name)) + ">" : "")
+ (IsArray? "[]" : ""); + (IsArray? "[]" : "");
// TODO: Alot of other generics stuff // TODO: Alot of other generics stuff
@@ -105,7 +107,7 @@ namespace Il2CppInspector.Reflection {
public bool IsGenericTypeDefinition { get; } public bool IsGenericTypeDefinition { get; }
public bool IsImport => (Attributes & TypeAttributes.Import) == TypeAttributes.Import; public bool IsImport => (Attributes & TypeAttributes.Import) == TypeAttributes.Import;
public bool IsInterface => (Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface; public bool IsInterface => (Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface;
public bool IsNested => DeclaringType != null; public bool IsNested => (MemberType & MemberTypes.NestedType) == MemberTypes.NestedType;
public bool IsNestedAssembly => (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedAssembly; public bool IsNestedAssembly => (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedAssembly;
public bool IsNestedFamANDAssem => (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamANDAssem; public bool IsNestedFamANDAssem => (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamANDAssem;
public bool IsNestedFamily => (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamily; public bool IsNestedFamily => (Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.NestedFamily;
@@ -125,10 +127,13 @@ namespace Il2CppInspector.Reflection {
// May get overridden by Il2CppType-based constructor below // May get overridden by Il2CppType-based constructor below
public override MemberTypes MemberType { get; } = MemberTypes.TypeInfo; public override MemberTypes MemberType { get; } = MemberTypes.TypeInfo;
public string BaseName => base.Name;
public override string Name { public override string Name {
get => (IsPointer ? "void *" : "") get => (IsPointer ? "void *" : "")
+ (base.Name.IndexOf("`", StringComparison.Ordinal) == -1? base.Name : base.Name.Remove(base.Name.IndexOf("`", StringComparison.Ordinal))) + (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)) + ">" : "") + (GenericTypeParameters != null? "<" + string.Join(", ", GenericTypeParameters.Select(x => x.Name)) + ">" : "")
+ (GenericTypeArguments != null ? "<" + string.Join(", ", GenericTypeArguments.Select(x => x.Name)) + ">" : "")
+ (IsArray ? "[]" : ""); + (IsArray ? "[]" : "");
protected set => base.Name = value; protected set => base.Name = value;
} }
@@ -266,20 +271,27 @@ namespace Il2CppInspector.Reflection {
public TypeInfo(Il2CppModel model, Il2CppType pType, MemberTypes memberType) { public TypeInfo(Il2CppModel model, Il2CppType pType, MemberTypes memberType) {
var image = model.Package.BinaryImage; var image = model.Package.BinaryImage;
// TODO: IsNested = true; // Finding TypeDefinitions adapted from il2cpp::vm::Class::FromIl2CppType
MemberType = memberType;
// TODO: Set Assembly and DeclaringType
// Generic type unresolved and concrete instance types // Generic type unresolved and concrete instance types
if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST) { if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_GENERICINST) {
var generic = image.ReadMappedObject<Il2CppGenericClass>(pType.datapoint); var generic = image.ReadMappedObject<Il2CppGenericClass>(pType.datapoint); // Il2CppGenericClass *
var genericTypeDef = model.TypesByDefinitionIndex[generic.typeDefinitionIndex]; var genericTypeDef = model.TypesByDefinitionIndex[generic.typeDefinitionIndex];
Assembly = genericTypeDef.Assembly;
Namespace = genericTypeDef.Namespace; Namespace = genericTypeDef.Namespace;
Name = genericTypeDef.Name; Name = genericTypeDef.BaseName;
Attributes |= TypeAttributes.Class; Attributes |= TypeAttributes.Class;
// Derived type?
if (genericTypeDef.Definition.parentIndex >= 0)
baseTypeUsage = genericTypeDef.Definition.parentIndex;
if (genericTypeDef.Definition.declaringTypeIndex >= 0) {
declaringTypeDefinitionIndex = (int)model.Package.TypeUsages[genericTypeDef.Definition.declaringTypeIndex].datapoint;
MemberType = memberType | MemberTypes.NestedType;
}
// TODO: Generic* properties and ContainsGenericParameters // TODO: Generic* properties and ContainsGenericParameters
// Get the instantiation // Get the instantiation
@@ -294,11 +306,13 @@ namespace Il2CppInspector.Reflection {
var argType = model.GetTypeFromVirtualAddress((ulong) pArg); var argType = model.GetTypeFromVirtualAddress((ulong) pArg);
// TODO: Detect whether unresolved or concrete (add concrete to GenericTypeArguments instead) // TODO: Detect whether unresolved or concrete (add concrete to GenericTypeArguments instead)
// TODO: GenericParameterPosition etc. in types we generate here // TODO: GenericParameterPosition etc. in types we generate here
// TODO: Assembly // TODO: Assembly etc.
GenericTypeArguments.Add(argType); // TODO: Fix MemberType here GenericTypeArguments.Add(argType); // TODO: Fix MemberType here
} }
} }
// TODO: Set Assembly, BaseType and DeclaringType for all of the below
// Array with known dimensions and bounds // Array with known dimensions and bounds
if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_ARRAY) { if (pType.type == Il2CppTypeEnum.IL2CPP_TYPE_ARRAY) {
var descriptor = image.ReadMappedObject<Il2CppArrayType>(pType.datapoint); var descriptor = image.ReadMappedObject<Il2CppArrayType>(pType.datapoint);