From 26d341db817828a79d9e13de6ae17d32372fff1f Mon Sep 17 00:00:00 2001 From: Katy Coe Date: Tue, 12 Nov 2019 04:19:52 +0100 Subject: [PATCH] Model: TypeInfo.GetAllTypeReferences() and TypeInfo.DeclaredMembers --- Il2CppInspector/Reflection/TypeInfo.cs | 89 +++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/Il2CppInspector/Reflection/TypeInfo.cs b/Il2CppInspector/Reflection/TypeInfo.cs index 2e15be6..5cbd1bd 100644 --- a/Il2CppInspector/Reflection/TypeInfo.cs +++ b/Il2CppInspector/Reflection/TypeInfo.cs @@ -74,7 +74,12 @@ namespace Il2CppInspector.Reflection { public List DeclaredConstructors { get; } = new List(); public List DeclaredEvents { get; } = new List(); public List DeclaredFields { get; } = new List(); - public List DeclaredMembers => throw new NotImplementedException(); + + public List DeclaredMembers => new IEnumerable[] { + DeclaredConstructors, DeclaredEvents, DeclaredFields, DeclaredMethods, + DeclaredNestedTypes?.ToList() ?? new List(), DeclaredProperties + }.SelectMany(m => m).ToList(); + public List DeclaredMethods { get; } = new List(); private int[] declaredNestedTypes; @@ -470,6 +475,88 @@ namespace Il2CppInspector.Reflection { DeclaringMethod = declaringMethod; } + // Get all the other types directly referenced by this type (single level depth; no recursion) + public List GetAllTypeReferences() { + var refs = new HashSet(); + + // Constructor, event, field, method, nested type, property attributes + var attrs = DeclaredMembers.Select(m => m.CustomAttributes).SelectMany(a => a); + refs.UnionWith(attrs.Select(a => a.AttributeType)); + + // Events + refs.UnionWith(DeclaredEvents.Select(e => e.EventHandlerType)); + + // Fields + refs.UnionWith(DeclaredFields.Select(f => f.FieldType)); + + // Properties (return type of getters or argument type of setters) + refs.UnionWith(DeclaredProperties.Select(p => p.PropertyType)); + + // Nested types + refs.UnionWith(DeclaredNestedTypes); + refs.UnionWith(DeclaredNestedTypes.Select(n => n.GetAllTypeReferences()).SelectMany(t => t)); + + // Constructors + refs.UnionWith(DeclaredConstructors.Select(m => m.DeclaredParameters).SelectMany(p => p).Select(p => p.ParameterType)); + + // Methods (includes event add/remove/raise, property get/set methods and extension methods) + refs.UnionWith(DeclaredMethods.Select(m => m.ReturnParameter.ParameterType)); + refs.UnionWith(DeclaredMethods.Select(m => m.DeclaredParameters).SelectMany(p => p).Select(p => p.ParameterType)); + + // Method generic type parameters and constraints + // TODO: Needs to recurse through nested generic parameters + refs.UnionWith(DeclaredMethods.Select(m => m.GenericTypeParameters ?? new List()).SelectMany(p => p)); + refs.UnionWith(DeclaredMethods.Select(m => m.GenericTypeParameters ?? new List()).SelectMany(p => p) + .Select(p => p.GetGenericParameterConstraints()).SelectMany(c => c)); + + // Type declaration attributes + refs.UnionWith(CustomAttributes.Select(a => a.AttributeType)); + + // Parent type + if (BaseType != null) + refs.Add(BaseType); + + // Declaring type + if (DeclaringType != null) + refs.Add(DeclaringType); + + // Element type + if (HasElementType) + refs.Add(ElementType); + + // Enum type + if (IsEnum) + refs.Add(GetEnumUnderlyingType()); + + // Generic type parameters and constraints + // TODO: Needs to recurse through nested generic parameters + if (GenericTypeParameters != null) + refs.UnionWith(GenericTypeParameters); + if (GenericTypeArguments != null) + refs.UnionWith(GenericTypeArguments); + refs.UnionWith(GetGenericParameterConstraints()); + + // Implemented interfaces + refs.UnionWith(ImplementedInterfaces); + + IEnumerable refList = refs.ToList(); + + // Repeatedly replace arrays, pointers and references with their element types + while (refList.Any(r => r.HasElementType)) + refList = refList.Select(r => r.HasElementType ? r.ElementType : r); + + // Remove anonymous types + refList = refList.Where(r => !string.IsNullOrEmpty(r.FullName)); + + // Eliminated named duplicates (the HashSet removes instance duplicates) + refList = refList.GroupBy(r => r.FullName).Select(p => p.First()); + + // Remove System.Object + refList = refList.Where(r => r.FullName != "System.Object"); + + return refList.ToList(); + } + // Display name of object public override string Name => IsGenericParameter ? base.Name : (HasElementType? ElementType.Name :