[XamlC] Resolve complex property type (#5086)
authorAkihiko Odaki <akihiko.odaki.4i@stu.hosei.ac.jp>
Fri, 15 Mar 2019 22:12:57 +0000 (07:12 +0900)
committerSamantha Houts <samhouts@users.noreply.github.com>
Fri, 15 Mar 2019 22:12:57 +0000 (15:12 -0700)
Xamarin.Forms.Build.Tasks/BindablePropertyReferenceExtensions.cs
Xamarin.Forms.Build.Tasks/PropertyDefinitionExtensions.cs [deleted file]
Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs
Xamarin.Forms.Xaml.UnitTests/XamlC/PropertyDefinitionExtensionsTests.cs [deleted file]
Xamarin.Forms.Xaml.UnitTests/XamlC/TypeReferenceExtensionsTests.cs

index a293057..641232b 100644 (file)
@@ -38,7 +38,7 @@ namespace Xamarin.Forms.Build.Tasks
                        var owner = bpRef.DeclaringType;
                        var bpName = bpRef.Name.EndsWith("Property", StringComparison.Ordinal) ? bpRef.Name.Substring(0, bpRef.Name.Length - 8) : bpRef.Name;
                        var property = owner.GetProperty(pd => pd.Name == bpName, out propertyDeclaringType);
-                       var propertyType = property?.ResolveGenericPropertyType(propertyDeclaringType, module);
+                       var propertyType = property?.PropertyType?.ResolveGenericParameters(propertyDeclaringType);
                        var staticGetter = owner.GetMethods(md => md.Name == $"Get{bpName}" &&
                                                                                                md.IsStatic &&
                                                                                                md.IsPublic &&
diff --git a/Xamarin.Forms.Build.Tasks/PropertyDefinitionExtensions.cs b/Xamarin.Forms.Build.Tasks/PropertyDefinitionExtensions.cs
deleted file mode 100644 (file)
index 8cbbbe4..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-using System;
-using Mono.Cecil;
-
-namespace Xamarin.Forms.Build.Tasks
-{
-       static class PropertyDefinitionExtensions
-       {
-               public static TypeReference ResolveGenericPropertyType(this PropertyDefinition self, TypeReference declaringTypeRef,
-                       ModuleDefinition module)
-               {
-                       if (self == null)
-                               throw new ArgumentNullException(nameof(self));
-                       if (declaringTypeRef == null)
-                               throw new ArgumentNullException(nameof(declaringTypeRef));
-                       if (!self.PropertyType.IsGenericParameter)
-                               return self.PropertyType;
-
-                       return ((GenericInstanceType)declaringTypeRef).GenericArguments [((GenericParameter)self.PropertyType).Position];
-               }
-       }
-}
\ No newline at end of file
index 0d455f6..df8ac79 100644 (file)
@@ -396,7 +396,7 @@ namespace Xamarin.Forms.Build.Tasks
                        TypeReference tPropertyRef = tSourceRef;
                        if (properties != null && properties.Count > 0) {
                                var lastProp = properties[properties.Count - 1];
-                               tPropertyRef = lastProp.property.ResolveGenericPropertyType(lastProp.propDeclTypeRef, module);
+                               tPropertyRef = lastProp.property.PropertyType.ResolveGenericParameters(lastProp.propDeclTypeRef);
                        }
                        tPropertyRef = module.ImportReference(tPropertyRef);
                        var valuetupleRef = context.Module.ImportReference(module.ImportReference(("mscorlib", "System", "ValueTuple`2")).MakeGenericInstanceType(new[] { tPropertyRef, module.TypeSystem.Boolean }));
@@ -478,7 +478,7 @@ namespace Xamarin.Forms.Build.Tasks
                                        var indexType = indexer.GetMethod.Parameters[0].ParameterType;
                                        if (!TypeRefComparer.Default.Equals(indexType, module.TypeSystem.String) && !TypeRefComparer.Default.Equals(indexType, module.TypeSystem.Int32))
                                                throw new XamlParseException($"Binding: Unsupported indexer index type: {indexType.FullName}", lineInfo);
-                                       previousPartTypeRef = indexer.ResolveGenericPropertyType(indexerDeclTypeRef, module);
+                                       previousPartTypeRef = indexer.PropertyType.ResolveGenericParameters(indexerDeclTypeRef);
                                }
                        }
                        return properties;
@@ -1160,7 +1160,7 @@ namespace Xamarin.Forms.Build.Tasks
                        var property = parent.VariableType.GetProperty(pd => pd.Name == localName, out declaringTypeReference);
                        if (property == null)
                                return false;
-                       var propertyType = property.ResolveGenericPropertyType(declaringTypeReference, module);
+                       var propertyType = property.PropertyType.ResolveGenericParameters(declaringTypeReference);
                        var propertySetter = property.SetMethod;
                        if (propertySetter == null || !propertySetter.IsPublic || propertySetter.IsStatic)
                                return false;
@@ -1224,7 +1224,7 @@ namespace Xamarin.Forms.Build.Tasks
                        module.ImportReference(parent.VariableType.ResolveCached());
                        var propertySetterRef = module.ImportReference(module.ImportReference(propertySetter).ResolveGenericParameters(declaringTypeReference, module));
                        propertySetterRef.ImportTypes(module);
-                       var propertyType = property.ResolveGenericPropertyType(declaringTypeReference, module);
+                       var propertyType = property.PropertyType.ResolveGenericParameters(declaringTypeReference);
                        var valueNode = node as ValueNode;
                        var elementNode = node as IElementNode;
 
index ac97e17..2dc73fe 100644 (file)
@@ -368,8 +368,19 @@ namespace Xamarin.Forms.Build.Tasks
 
                public static TypeReference ResolveGenericParameters(this TypeReference self, TypeReference declaringTypeReference)
                {
+                       var genericdeclType = declaringTypeReference as GenericInstanceType;
+                       if (genericdeclType == null)
+                               return self;
+
+                       var genericParameterSelf = self as GenericParameter;
+                       if (genericParameterSelf != null)
+                               return genericdeclType.GenericArguments[genericParameterSelf.Position];
+
                        var genericself = self as GenericInstanceType;
-                       return genericself == null ? self : genericself.ResolveGenericParameters(declaringTypeReference);
+                       if (genericself != null)
+                               return genericself.ResolveGenericParameters(declaringTypeReference);
+
+                       return self;
                }
 
                public static GenericInstanceType ResolveGenericParameters(this GenericInstanceType self, TypeReference declaringTypeReference)
@@ -378,13 +389,18 @@ namespace Xamarin.Forms.Build.Tasks
                        if (genericdeclType == null)
                                return self;
 
+                       return self.ResolveGenericParameters(genericdeclType);
+               }
+
+               public static GenericInstanceType ResolveGenericParameters(this GenericInstanceType self, GenericInstanceType declaringTypeReference)
+               {
                        List<TypeReference> args = new List<TypeReference>();
                        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]);
+                                       args.Add(declaringTypeReference.GenericArguments[genericParameter.Position]);
                        }
                        return self.ElementType.MakeGenericInstanceType(args.ToArray());
                }
diff --git a/Xamarin.Forms.Xaml.UnitTests/XamlC/PropertyDefinitionExtensionsTests.cs b/Xamarin.Forms.Xaml.UnitTests/XamlC/PropertyDefinitionExtensionsTests.cs
deleted file mode 100644 (file)
index 93146ac..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-using System;
-using System.Linq;
-
-using Mono.Cecil;
-
-using Xamarin.Forms.Build.Tasks;
-
-using NUnit.Framework;
-using System.Collections.Generic;
-
-namespace Xamarin.Forms.XamlcUnitTests
-{
-       [TestFixture]
-       public class PropertyDefinitionExtensionsTests
-       {
-               public class NonGenericClass
-               {
-                       public object Property { get; set; }
-               }
-
-               public class GenericClass<T, U, V>
-               {
-                       public object Property { get; set; }
-                       public T GenericT { get; set; }
-                       public U GenericU { get; set; }
-                       public V GenericV { get; set; }
-                       public IEnumerable<T> EnumerableT { get; set; }
-                       public KeyValuePair<V, U> KvpVU { get; set; }
-               }
-
-               ModuleDefinition module;
-
-               [SetUp]
-               public void SetUp ()
-               {
-                       module = ModuleDefinition.CreateModule ("foo", ModuleKind.Dll);
-               }
-
-               [Test]
-               public void ResolveGenericPropertyType ()
-               {
-                       var type = module.ImportReference (typeof (GenericClass<bool, string, int>));
-                       TypeReference declaringTypeReference;
-                       var prop = type.GetProperty (fd => fd.Name == "Property", out declaringTypeReference);
-                       var propertyType = prop.ResolveGenericPropertyType (declaringTypeReference, module);
-                       Assert.AreEqual ("System.Object", propertyType.FullName);
-
-                       prop = type.GetProperty(fd => fd.Name == "GenericT", out declaringTypeReference);
-                       propertyType = prop.ResolveGenericPropertyType(declaringTypeReference, module);
-                       Assert.AreEqual("System.Boolean", propertyType.FullName);
-
-                       prop = type.GetProperty(fd => fd.Name == "GenericU", out declaringTypeReference);
-                       propertyType = prop.ResolveGenericPropertyType(declaringTypeReference, module);
-                       Assert.AreEqual("System.String", propertyType.FullName);
-
-                       prop = type.GetProperty(fd => fd.Name == "GenericV", out declaringTypeReference);
-                       propertyType = prop.ResolveGenericPropertyType(declaringTypeReference, module);
-                       Assert.AreEqual("System.Int32", propertyType.FullName);
-
-               }
-       }
-}
\ No newline at end of file
index 8706602..97c6b83 100644 (file)
@@ -151,6 +151,17 @@ namespace Xamarin.Forms.XamlcUnitTests
                        Assert.False(TestInheritsFromOrImplements(test.GetType("Xamarin.Forms.Effect"), core.GetType("Xamarin.Forms.Effect")));
                }
 
+               [Test]
+               public void TestResolveSelectedGenericParameter()
+               {
+                       var imported = module.ImportReference(typeof(Bar<byte>));
+                       var baseType = (GenericInstanceType)imported.Resolve().BaseType;
+                       var resolvedType = baseType.GenericArguments[0].ResolveGenericParameters(imported);
+
+                       Assert.AreEqual("System", resolvedType.Namespace);
+                       Assert.AreEqual("Byte", resolvedType.Name);
+               }
+
                [TestCase(typeof(Bar<byte>), 1)]
                [TestCase(typeof(Quux<byte>), 2)]
                [TestCase(typeof(Corge<byte>), 3)]