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

View File

@@ -21,15 +21,48 @@ namespace Il2CppInspector.Reflection {
// Undefined if the Type represents a generic type parameter // Undefined if the Type represents a generic type parameter
public TypeAttributes Attributes { get; } public TypeAttributes Attributes { get; }
// Type that this type inherits from public TypeInfo BaseType {
private readonly int baseTypeReference = -1; 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 : public override TypeInfo DeclaringType {
baseTypeReference != -1? get {
Assembly.Model.TypesByReferenceIndex[baseTypeReference] if (Definition != null) {
: IsArray? Assembly.Model.TypesByFullName["System.Array"] /* Type definition */
: Namespace != "System" || BaseName != "Object" ? Assembly.Model.TypesByFullName["System.Object"] if (Definition.declaringTypeIndex == -1)
: null; 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 // True if the type contains unresolved generic type parameters
public bool ContainsGenericParameters => IsGenericParameter || genericArguments.Any(ga => ga.ContainsGenericParameters); public bool ContainsGenericParameters => IsGenericParameter || genericArguments.Any(ga => ga.ContainsGenericParameters);
@@ -68,6 +101,11 @@ namespace Il2CppInspector.Reflection {
return types; 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 // Get a method by its name
public MethodInfo GetMethod(string name) => DeclaredMethods.FirstOrDefault(m => m.Name == 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 // 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 // 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 // IsGenericTypeParameter and IsGenericMethodParameter from https://github.com/dotnet/corefx/issues/23883
public bool IsGenericTypeParameter => IsGenericParameter && DeclaringMethod == null; public bool IsGenericTypeParameter => IsGenericParameter && DeclaringMethod == null;
@@ -526,13 +564,8 @@ namespace Il2CppInspector.Reflection {
Namespace = pkg.Strings[Definition.namespaceIndex]; Namespace = pkg.Strings[Definition.namespaceIndex];
Name = pkg.Strings[Definition.nameIndex]; Name = pkg.Strings[Definition.nameIndex];
// Derived type?
if (Definition.parentIndex >= 0)
baseTypeReference = Definition.parentIndex;
// Nested type? // Nested type?
if (Definition.declaringTypeIndex >= 0) { if (Definition.declaringTypeIndex >= 0) {
declaringTypeDefinitionIndex = (int) pkg.TypeReferences[Definition.declaringTypeIndex].datapoint;
MemberType |= MemberTypes.NestedType; MemberType |= MemberTypes.NestedType;
} }
@@ -736,7 +769,9 @@ namespace Il2CppInspector.Reflection {
} }
// Initialize a type from a concrete generic instance // 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 // Same visibility attributes as generic type definition
Attributes = genericTypeDefinition.Attributes; Attributes = genericTypeDefinition.Attributes;
@@ -746,16 +781,7 @@ namespace Il2CppInspector.Reflection {
// Same name as generic type definition // Same name as generic type definition
Namespace = genericTypeDefinition.Namespace; Namespace = genericTypeDefinition.Namespace;
Name = genericTypeDefinition.BaseName; // use BaseName to exclude the type parameters so we can supply our own Name = genericTypeDefinition.BaseName; // use BaseName to exclude the type parameters so we can supply our own
MemberType = genericTypeDefinition.MemberType;
// 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;
}
IsGenericParameter = false; IsGenericParameter = false;
IsGenericType = true; IsGenericType = true;