Remove index from BaseType, DeclaringType

All types will need to eventually be fully generic. Therefore, we need
to eliminate indices when referring to types, and also be very lazy when
accessing TypeInfo properties so that we don't access uninitialized
types during model creation.
This commit is contained in:
Robert Xiao
2020-04-10 03:56:42 -07:00
committed by Katy
parent 6ddb502e96
commit f0124d9290
2 changed files with 57 additions and 34 deletions

View File

@@ -20,8 +20,7 @@ namespace Il2CppInspector.Reflection {
public CustomAttributeData[] GetCustomAttributes(string fullTypeName) => CustomAttributes.Where(a => a.AttributeType.FullName == fullTypeName).ToArray();
// Type that this type is declared in for nested types
protected int declaringTypeDefinitionIndex { private get; set; } = -1;
public TypeInfo DeclaringType => declaringTypeDefinitionIndex != -1? Assembly.Model.TypesByDefinitionIndex[declaringTypeDefinitionIndex] : null;
public virtual TypeInfo DeclaringType { get; private set; }
// What sort of member this is, eg. method, field etc.
public abstract MemberTypes MemberType { get; }
@@ -36,11 +35,9 @@ namespace Il2CppInspector.Reflection {
protected MemberInfo(Assembly asm) => Assembly = asm;
// For lower level members, eg. fields, properties etc. and nested types
protected MemberInfo(TypeInfo declaringType = null) {
if (declaringType != null) {
protected MemberInfo(TypeInfo declaringType) {
Assembly = declaringType.Assembly;
declaringTypeDefinitionIndex = declaringType.Index;
}
DeclaringType = declaringType;
}
public override string ToString() => Name;

View File

@@ -21,15 +21,48 @@ namespace Il2CppInspector.Reflection {
// Undefined if the Type represents a generic type parameter
public TypeAttributes Attributes { get; }
// Type that this type inherits from
private readonly int baseTypeReference = -1;
public TypeInfo BaseType {
get {
if (IsPointer || IsByRef)
return null;
if (IsArray)
return Assembly.Model.TypesByFullName["System.Array"];
if (Definition != null) {
if (Definition.parentIndex >= 0)
return Assembly.Model.TypesByReferenceIndex[Definition.parentIndex];
}
if (genericTypeDefinition != null) {
/* TODO substitute generic arguments */
return genericTypeDefinition.BaseType;
}
if (Namespace != "System" || BaseName != "Object")
return Assembly.Model.TypesByFullName["System.Object"];
return null;
}
}
public TypeInfo BaseType => IsPointer? null :
baseTypeReference != -1?
Assembly.Model.TypesByReferenceIndex[baseTypeReference]
: IsArray? Assembly.Model.TypesByFullName["System.Array"]
: Namespace != "System" || BaseName != "Object" ? Assembly.Model.TypesByFullName["System.Object"]
: null;
public override TypeInfo DeclaringType {
get {
if (Definition != null) {
/* Type definition */
if (Definition.declaringTypeIndex == -1)
return null;
var type = Assembly.Model.TypesByReferenceIndex[Definition.declaringTypeIndex];
if (type == null) {
/* This might happen while initially setting up the types */
var typeRef = Assembly.Model.Package.TypeReferences[Definition.declaringTypeIndex];
type = Assembly.Model.TypesByDefinitionIndex[(int)typeRef.datapoint];
}
return type;
}
if (genericTypeDefinition != null) {
/* Generic type instance */
/* TODO substitute generic arguments */
return genericTypeDefinition.DeclaringType;
}
return base.DeclaringType;
}
}
// True if the type contains unresolved generic type parameters
public bool ContainsGenericParameters => IsGenericParameter || genericArguments.Any(ga => ga.ContainsGenericParameters);
@@ -68,6 +101,11 @@ namespace Il2CppInspector.Reflection {
return types;
}
private readonly TypeInfo genericTypeDefinition;
/* https://docs.microsoft.com/en-us/dotnet/api/system.type.getgenerictypedefinition?view=netframework-4.8 */
public TypeInfo GetGenericTypeDefinition() => genericTypeDefinition;
// Get a method by its name
public MethodInfo GetMethod(string name) => DeclaredMethods.FirstOrDefault(m => m.Name == name);
@@ -102,7 +140,7 @@ namespace Il2CppInspector.Reflection {
// Method that the type is declared in if this is a type parameter of a generic method
// TODO: Make a unit test from this: https://docs.microsoft.com/en-us/dotnet/api/system.type.declaringmethod?view=netframework-4.8
public MethodBase DeclaringMethod;
public MethodBase DeclaringMethod { get; }
// IsGenericTypeParameter and IsGenericMethodParameter from https://github.com/dotnet/corefx/issues/23883
public bool IsGenericTypeParameter => IsGenericParameter && DeclaringMethod == null;
@@ -526,13 +564,8 @@ namespace Il2CppInspector.Reflection {
Namespace = pkg.Strings[Definition.namespaceIndex];
Name = pkg.Strings[Definition.nameIndex];
// Derived type?
if (Definition.parentIndex >= 0)
baseTypeReference = Definition.parentIndex;
// Nested type?
if (Definition.declaringTypeIndex >= 0) {
declaringTypeDefinitionIndex = (int) pkg.TypeReferences[Definition.declaringTypeIndex].datapoint;
MemberType |= MemberTypes.NestedType;
}
@@ -736,7 +769,9 @@ namespace Il2CppInspector.Reflection {
}
// Initialize a type from a concrete generic instance
public TypeInfo(TypeInfo genericTypeDefinition, Il2CppGenericInst instance) : base(genericTypeDefinition.Assembly) {
public TypeInfo(TypeInfo genericTypeDef, Il2CppGenericInst instance) : base(genericTypeDef.Assembly) {
genericTypeDefinition = genericTypeDef;
// Same visibility attributes as generic type definition
Attributes = genericTypeDefinition.Attributes;
@@ -746,16 +781,7 @@ namespace Il2CppInspector.Reflection {
// Same name as generic type definition
Namespace = genericTypeDefinition.Namespace;
Name = genericTypeDefinition.BaseName; // use BaseName to exclude the type parameters so we can supply our own
// Derived type?
if (genericTypeDefinition.Definition.parentIndex >= 0)
baseTypeReference = genericTypeDefinition.Definition.parentIndex;
// Nested type?
if (genericTypeDefinition.Definition.declaringTypeIndex >= 0) {
declaringTypeDefinitionIndex = (int)Assembly.Model.Package.TypeReferences[genericTypeDefinition.Definition.declaringTypeIndex].datapoint;
MemberType |= MemberTypes.NestedType;
}
MemberType = genericTypeDefinition.MemberType;
IsGenericParameter = false;
IsGenericType = true;
@@ -816,7 +842,7 @@ namespace Il2CppInspector.Reflection {
// Initialize a type that is a reference or pointer to the specified type
private TypeInfo(TypeInfo underlyingType, bool isPointer) : base(underlyingType.Assembly) {
ElementType = underlyingType;
if(isPointer) {
if (isPointer) {
IsPointer = true;
} else {
IsByRef = true;