fixes BindableLayout DataTemplate - XamlC #5486 (#6178)
authorinforithmics <thomas.stocker@gmail.com>
Mon, 20 May 2019 18:00:46 +0000 (20:00 +0200)
committerSamantha Houts <samhouts@users.noreply.github.com>
Mon, 20 May 2019 18:00:46 +0000 (11:00 -0700)
fixes #5651
fixes #5486

* Update TypeReferenceExtensions.cs

Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs
Xamarin.Forms.Xaml.UnitTests/Issues/Gh5486.xaml [new file with mode: 0644]
Xamarin.Forms.Xaml.UnitTests/Issues/Gh5486.xaml.cs [new file with mode: 0644]
Xamarin.Forms.Xaml.UnitTests/Issues/Gh5651.xaml [new file with mode: 0644]
Xamarin.Forms.Xaml.UnitTests/Issues/Gh5651.xaml.cs [new file with mode: 0644]

index 2e7338a..32890c5 100644 (file)
@@ -472,7 +472,7 @@ namespace Xamarin.Forms.Build.Tasks
                                        var property = previousPartTypeRef.GetProperty(pd => pd.Name == p && pd.GetMethod != null && pd.GetMethod.IsPublic, out var propDeclTypeRef)
                                                                          ?? throw new XamlParseException($"Binding: Property '{p}' not found on '{previousPartTypeRef}'", lineInfo);
                                        properties.Add((property, propDeclTypeRef, null));
-                                       previousPartTypeRef = property.PropertyType;
+                                       previousPartTypeRef = property.PropertyType.ResolveGenericParameters(propDeclTypeRef);
                                }
                                if (indexArg != null) {
                                        var defaultMemberAttribute = previousPartTypeRef.GetCustomAttribute(module, ("mscorlib", "System.Reflection", "DefaultMemberAttribute"));
index 2dc73fe..1064e08 100644 (file)
@@ -71,7 +71,7 @@ namespace Xamarin.Forms.Build.Tasks
                                return properties.Single();
                        if (typeDef.IsInterface) {
                                foreach (var face in typeDef.Interfaces) {
-                                       var p = face.InterfaceType.GetProperty(predicate, out var interfaceDeclaringTypeRef);
+                                       var p = face.InterfaceType.ResolveGenericParameters(typeRef).GetProperty(predicate, out var interfaceDeclaringTypeRef);
                                        if (p != null) {
                                                declaringTypeRef = interfaceDeclaringTypeRef;
                                                return p;
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Gh5486.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Gh5486.xaml
new file mode 100644 (file)
index 0000000..6f03c28
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+               xmlns="http://xamarin.com/schemas/2014/forms"
+               xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+               xmlns:local="using:Xamarin.Forms.Xaml.UnitTests"
+               x:Class="Xamarin.Forms.Xaml.UnitTests.Gh5486"
+               x:DataType="local:IGh5486VM">
+    <Label x:Name="label" Text="{Binding Data.Label}" />
+</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Gh5486.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Gh5486.xaml.cs
new file mode 100644 (file)
index 0000000..e1dc122
--- /dev/null
@@ -0,0 +1,76 @@
+using NUnit.Framework;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+       public class Gh5486VM : IGh5486VM
+       {
+               public Gh5486VM()
+               {
+                       this.Data = new Tag5486()
+                       {
+                               Label = "test",
+                       };
+               }
+
+               public ITag5486 Data { get; set; }
+       }
+
+       public class Tag5486 : ITag5486
+       {
+               public string Label { get; set; }
+       }
+
+       public interface ITag5486
+       {
+               string Label { get; set; }
+       }
+
+       public interface IGh5486VM : IGh5486VMBase<ITag5486>
+       {
+       }
+
+       public interface IGh5486VMBase<T>
+       {
+               T Data { get; }
+       }
+
+       [XamlCompilation(XamlCompilationOptions.Compile)]
+       public partial class Gh5486 : ContentPage
+       {
+               public Gh5486()
+               {
+                       InitializeComponent();
+               }
+
+               public Gh5486(bool useCompiledXaml)
+               {
+                       //this stub will be replaced at compile time
+               }
+
+               [TestFixture]
+               class Tests
+               {
+                       [SetUp]
+                       public void Setup()
+                       {
+                               Device.PlatformServices = new MockPlatformServices();
+                       }
+
+                       [TearDown]
+                       public void TearDown()
+                       {
+                               Device.PlatformServices = null;
+                       }
+
+                       [TestCase(true), TestCase(false)]
+                       public void GenericBaseInterfaceResolution(bool useCompiledXaml)
+                       {
+                               if (useCompiledXaml)
+                                       Assert.DoesNotThrow(() => MockCompiler.Compile(typeof(Gh5486)));
+                               var layout = new Gh5486(useCompiledXaml) { BindingContext = new Gh5486VM() };
+                               Assert.That(layout.label.Text, Is.EqualTo("test"));
+                       }
+               }
+       }
+}
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Gh5651.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Gh5651.xaml
new file mode 100644 (file)
index 0000000..5783fbc
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ContentPage
+               xmlns="http://xamarin.com/schemas/2014/forms"
+               xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+               xmlns:local="using:Xamarin.Forms.Xaml.UnitTests"
+               x:Class="Xamarin.Forms.Xaml.UnitTests.Gh5651"
+               x:DataType="local:IViewModel5651">
+    <Label x:Name="label" Text="{Binding SelectedItem}" />
+</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Gh5651.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Gh5651.xaml.cs
new file mode 100644 (file)
index 0000000..dae6787
--- /dev/null
@@ -0,0 +1,63 @@
+using NUnit.Framework;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+       public class Gh5651VM : IViewModel5651
+       {
+               public Gh5651VM()
+               {
+                       this.SelectedItem = "test";
+               }
+
+               public string SelectedItem { get; set; }
+       }
+
+       public interface IViewModel5651 : IEditViewModel5651<string>{}
+
+       public interface IEditViewModel5651<T> : IBaseViewModel5651<T>{}
+
+       public interface IBaseViewModel5651<T>
+       {
+               T SelectedItem { get; set; }
+       }
+
+       [XamlCompilation(XamlCompilationOptions.Compile)]
+       public partial class Gh5651 : ContentPage
+       {
+               public Gh5651()
+               {
+                       InitializeComponent();
+               }
+
+               public Gh5651(bool useCompiledXaml)
+               {
+                       //this stub will be replaced at compile time
+               }
+
+               [TestFixture]
+               class Tests
+               {
+                       [SetUp]
+                       public void Setup()
+                       {
+                               Device.PlatformServices = new MockPlatformServices();
+                       }
+
+                       [TearDown]
+                       public void TearDown()
+                       {
+                               Device.PlatformServices = null;
+                       }
+
+                       [TestCase(true), TestCase(false)]
+                       public void GenericBaseInterfaceResolution(bool useCompiledXaml)
+                       {
+                               if (useCompiledXaml)
+                                       Assert.DoesNotThrow(() => MockCompiler.Compile(typeof(Gh5651)));
+                               var layout = new Gh5651(useCompiledXaml) { BindingContext = new Gh5651VM() };
+                               Assert.That(layout.label.Text, Is.EqualTo("test"));
+                       }
+               }
+       }
+}