From 871c368e492b9cb55675a3a83142742afd087563 Mon Sep 17 00:00:00 2001 From: Katy Coe Date: Wed, 29 Jan 2020 08:46:46 +0100 Subject: [PATCH] Model: Implement GenericParameterPosition for TypeRefs --- Il2CppInspector/Reflection/TypeInfo.cs | 12 +++++++++-- Il2CppTests/TestGenericTypes.cs | 27 ++++++++++++++++--------- Il2CppTests/TestSources/GenericTypes.cs | 4 +++- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/Il2CppInspector/Reflection/TypeInfo.cs b/Il2CppInspector/Reflection/TypeInfo.cs index ba91b2c..d55c5b0 100644 --- a/Il2CppInspector/Reflection/TypeInfo.cs +++ b/Il2CppInspector/Reflection/TypeInfo.cs @@ -352,7 +352,13 @@ namespace Il2CppInspector.Reflection { public GenericParameterAttributes GenericParameterAttributes { get; } - public int GenericParameterPosition { get; } + // Generic parameter position in list of non-concrete type parameters + // See: https://docs.microsoft.com/en-us/dotnet/api/system.type.genericparameterposition?view=netframework-4.8 + private int genericParameterPosition; + public int GenericParameterPosition { + get => IsGenericParameter ? genericParameterPosition : throw new InvalidOperationException("The current type does not represent a type parameter"); + private set => genericParameterPosition = value; + } public List GenericTypeParameters { get; } @@ -613,7 +619,6 @@ namespace Il2CppInspector.Reflection { foreach (var pArg in genericTypeArguments) { var argType = model.GetTypeFromVirtualAddress((ulong) pArg); // TODO: Detect whether unresolved or concrete (add concrete to GenericTypeArguments instead) - // TODO: GenericParameterPosition etc. in types we generate here // TODO: Assembly etc. GenericTypeArguments.Add(argType); // TODO: Fix MemberType here } @@ -682,6 +687,9 @@ namespace Il2CppInspector.Reflection { if (container.is_method == 1) DeclaringMethod = model.MethodsByDefinitionIndex[container.ownerIndex]; + // Set position in argument list + GenericParameterPosition = paramType.num; + IsGenericParameter = true; ContainsGenericParameters = true; IsGenericType = false; diff --git a/Il2CppTests/TestGenericTypes.cs b/Il2CppTests/TestGenericTypes.cs index 7c071be..252a1d9 100644 --- a/Il2CppTests/TestGenericTypes.cs +++ b/Il2CppTests/TestGenericTypes.cs @@ -1,5 +1,5 @@ /* - Copyright 2019 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com + Copyright 2019-2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com All rights reserved. */ @@ -29,31 +29,37 @@ namespace Il2CppInspector var asm = model.GetAssembly("GenericTypes.dll"); // Act + TypeInfo tBase = asm.GetType("Il2CppTests.TestSources.Base`2"); TypeInfo tDerived = asm.GetType("Il2CppTests.TestSources.Derived`1"); TypeInfo tDerivedBase = tDerived.BaseType; // TODO: array of Derived // TypeInfo tDerivedArray - TypeInfo tT = asm.GetType("Il2CppTests.TestSources.Base`2").GenericTypeParameters[0]; + TypeInfo tT = tBase.GenericTypeParameters[0]; + TypeInfo tU = tBase.GenericTypeParameters[1]; TypeInfo tF = tDerived.GetField("F").FieldType; TypeInfo tNested = asm.GetType("Il2CppTests.TestSources.Derived`1+Nested"); + DisplayGenericType(tBase, "Generic type definition Base"); DisplayGenericType(tDerived, "Derived"); DisplayGenericType(tDerivedBase, "Base type of Derived"); //DisplayGenericType(tDerivedArray, "Array of Derived"); - DisplayGenericType(tT, "Type parameter T from Base"); + DisplayGenericType(tT, "Type parameter T from Base"); + DisplayGenericType(tU, "Type parameter U from Base"); DisplayGenericType(tF, "Field type, G>"); DisplayGenericType(tNested, "Nested type in Derived"); // Assert var checks = new[] { - (tDerived, "Derived`1[V]", true, true, true, false), - (tDerivedBase, "Base`2[System.String,V]", true, false, true, false), - //(tDerivedArray, "Derived`1[System.Int32][]", false, false, false, false), - (tT, "T", false, false, true, true), - (tF, "G`1[Derived`1[V]]", true, false, true, false), - (tNested, "Derived`1[V]+Nested[V]", true, true, true, false) + (tBase, "Base`2[T,U]", true, true, true, false, -1), + (tDerived, "Derived`1[V]", true, true, true, false, -1), + (tDerivedBase, "Base`2[System.String,V]", true, false, true, false, -1), + //(tDerivedArray, "Derived`1[System.Int32][]", false, false, false, false, -1), + (tT, "T", false, false, true, true, 0), + (tU, "U", false, false, true, true, 1), + (tF, "G`1[Derived`1[V]]", true, false, true, false, -1), + (tNested, "Derived`1[V]+Nested[V]", true, true, true, false, -1) }; foreach (var check in checks) { @@ -75,6 +81,9 @@ namespace Il2CppInspector Console.WriteLine("\t IsGenericTypeDefinition: {0}", t.IsGenericTypeDefinition); Console.WriteLine("\tContainsGenericParameters: {0}", t.ContainsGenericParameters); Console.WriteLine("\t IsGenericParameter: {0}", t.IsGenericParameter); + + if (t.IsGenericParameter) + Console.WriteLine("\t GenericParameterPosition: {0}", t.GenericParameterPosition); } } } diff --git a/Il2CppTests/TestSources/GenericTypes.cs b/Il2CppTests/TestSources/GenericTypes.cs index 87a6c7b..4432aa9 100644 --- a/Il2CppTests/TestSources/GenericTypes.cs +++ b/Il2CppTests/TestSources/GenericTypes.cs @@ -1,5 +1,5 @@ /* - Copyright 2017-2019 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com + Copyright 2017-2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com All rights reserved. */ @@ -45,6 +45,8 @@ namespace Il2CppTests.TestSources Type tF = tDerived.GetField("F").FieldType; Type tNested = typeof(Derived<>.Nested); } + + private void forceTypeReferenceToDerivedIntArray(Derived typeRef) {} } // Constraints on type definitions