From 8f3804de4dc63d41ef9687cfa38bff8238c5743a Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Sun, 23 Dec 2018 01:58:06 +0900 Subject: [PATCH] [XamlC] Test generic parameters to evaluate equality of types (#4062) --- .../TypeReferenceExtensions.cs | 51 ++++++++++++++++++---- .../XamlC/TypeReferenceExtensionsTests.cs | 1 + 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs b/Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs index 99f3477..eebc0a9 100644 --- a/Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs +++ b/Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs @@ -205,8 +205,6 @@ namespace Xamarin.Forms.Build.Tasks if (typeRef.FullName == "System.Object") return false; var typeDef = typeRef.ResolveCached(); - if (TypeRefComparer.Default.Equals(typeDef, baseClass.ResolveCached())) - return true; if (typeDef.Interfaces.Any(ir => TypeRefComparer.Default.Equals(ir.InterfaceType.ResolveGenericParameters(typeRef), baseClass))) return true; if (typeDef.BaseType == null) @@ -324,7 +322,7 @@ namespace Xamarin.Forms.Build.Tasks returnType = ((GenericInstanceType)opDeclTypeRef).GenericArguments [((GenericParameter)returnType).Position]; if (!returnType.InheritsFromOrImplements(toType)) continue; - var paramType = cast.Parameters[0].ParameterType; + var paramType = cast.Parameters[0].ParameterType.ResolveGenericParameters(castDef); if (!fromType.InheritsFromOrImplements(paramType)) continue; return castDef; @@ -333,22 +331,57 @@ namespace Xamarin.Forms.Build.Tasks return null; } - public static TypeReference ResolveGenericParameters(this TypeReference self, TypeReference declaringTypeReference) + public static TypeReference ResolveGenericParameters(this TypeReference self, MethodReference declaringMethodReference) { + var genericParameterSelf = self as GenericParameter; + var genericdeclMethod = declaringMethodReference as GenericInstanceMethod; + var declaringTypeReference = declaringMethodReference.DeclaringType; + var genericdeclType = declaringTypeReference as GenericInstanceType; + + if (genericParameterSelf != null) { + switch (genericParameterSelf.Type) { + case GenericParameterType.Method: + self = genericdeclMethod.GenericArguments[genericParameterSelf.Position]; + break; + + case GenericParameterType.Type: + self = genericdeclType.GenericArguments[genericParameterSelf.Position]; + break; + } + } + var genericself = self as GenericInstanceType; if (genericself == null) return self; + genericself = genericself.ResolveGenericParameters(declaringTypeReference); + for (var i = 0; i < genericself.GenericArguments.Count; i++) { + var genericParameter = genericself.GenericArguments[i] as GenericParameter; + if (genericParameter != null) + genericself.GenericArguments[i] = genericdeclMethod.GenericArguments[genericParameter.Position]; + } + return genericself; + } + + public static TypeReference ResolveGenericParameters(this TypeReference self, TypeReference declaringTypeReference) + { + var genericself = self as GenericInstanceType; + return genericself == null ? self : genericself.ResolveGenericParameters(declaringTypeReference); + } + + public static GenericInstanceType ResolveGenericParameters(this GenericInstanceType self, TypeReference declaringTypeReference) + { var genericdeclType = declaringTypeReference as GenericInstanceType; if (genericdeclType == null) return self; List args = new List(); - for (var i = 0; i < genericself.GenericArguments.Count; i++) { - if (!genericself.GenericArguments[i].IsGenericParameter) - args.Add(genericself.GenericArguments[i].ResolveGenericParameters(declaringTypeReference)); - else - args.Add(genericdeclType.GenericArguments[(genericself.GenericArguments[i] as GenericParameter).Position]); + for (var i = 0; i < self.GenericArguments.Count; i++) { + var genericParameter = self.GenericArguments[i] as GenericParameter; + if (genericParameter == null) + args.Add(self.GenericArguments[i].ResolveGenericParameters(declaringTypeReference)); + else if (genericParameter.Type == GenericParameterType.Type) + args.Add(genericdeclType.GenericArguments[genericParameter.Position]); } return self.GetElementType().MakeGenericInstanceType(args.ToArray()); } diff --git a/Xamarin.Forms.Xaml.UnitTests/XamlC/TypeReferenceExtensionsTests.cs b/Xamarin.Forms.Xaml.UnitTests/XamlC/TypeReferenceExtensionsTests.cs index 3400b2e..f537dd1 100644 --- a/Xamarin.Forms.Xaml.UnitTests/XamlC/TypeReferenceExtensionsTests.cs +++ b/Xamarin.Forms.Xaml.UnitTests/XamlC/TypeReferenceExtensionsTests.cs @@ -111,6 +111,7 @@ namespace Xamarin.Forms.XamlcUnitTests [TestCase(typeof(StackLayout), typeof(View), ExpectedResult = true)] [TestCase(typeof(Foo), typeof(Foo), ExpectedResult = true)] [TestCase(typeof(Bar), typeof(Foo), ExpectedResult = true)] + [TestCase(typeof(Bar), typeof(Foo), ExpectedResult = false)] [TestCase(typeof(Bar), typeof(Foo), ExpectedResult = true)] [TestCase(typeof(Qux), typeof(double), ExpectedResult = false)] //https://github.com/xamarin/Xamarin.Forms/issues/1497 public bool TestInheritsFromOrImplements(Type typeRef, Type baseClass) -- 2.7.4