[XamlC] Resolve generic base type on GetProperty (#3394)

GetMethod, GetField, ... were already correctly resolving generic base
types. GetProperty or GetEvent were not, causing NRE later on.

- fixes #3260
This commit is contained in:
Stephane Delcroix 2018-07-26 11:22:51 +02:00 коммит произвёл GitHub
Родитель 7cf3725e9d
Коммит 3878335d60
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 86 добавлений и 9 удалений

Просмотреть файл

@ -799,7 +799,6 @@ namespace Xamarin.Forms.Build.Tasks
var localName = propertyName.LocalName;
bool attached;
var bpRef = GetBindablePropertyReference(parent, propertyName.NamespaceURI, ref localName, out attached, context, lineInfo);
TypeReference _;
//If it's a BP, GetValue ()
if (CanGetValue(parent, bpRef, attached, lineInfo, context, out _))
@ -1181,8 +1180,7 @@ namespace Xamarin.Forms.Build.Tasks
static IEnumerable<Instruction> Get(VariableDefinition parent, string localName, IXmlLineInfo iXmlLineInfo, ILContext context, out TypeReference propertyType)
{
var module = context.Body.Method.Module;
TypeReference declaringTypeReference;
var property = parent.VariableType.GetProperty(pd => pd.Name == localName, out declaringTypeReference);
var property = parent.VariableType.GetProperty(pd => pd.Name == localName, out var declaringTypeReference);
var propertyGetter = property.GetMethod;
module.ImportReference(parent.VariableType.ResolveCached());

Просмотреть файл

@ -70,7 +70,7 @@ namespace Xamarin.Forms.Build.Tasks
return properties.Single();
if (typeDef.BaseType == null || typeDef.BaseType.FullName == "System.Object")
return null;
return typeDef.BaseType.GetProperty(predicate, out declaringTypeRef);
return typeDef.BaseType.ResolveGenericParameters(typeRef).GetProperty(predicate, out declaringTypeRef);
}
public static EventDefinition GetEvent(this TypeReference typeRef, Func<EventDefinition, bool> predicate,
@ -85,7 +85,7 @@ namespace Xamarin.Forms.Build.Tasks
}
if (typeDef.BaseType == null || typeDef.BaseType.FullName == "System.Object")
return null;
return typeDef.BaseType.GetEvent(predicate, out declaringTypeRef);
return typeDef.BaseType.ResolveGenericParameters(typeRef).GetEvent(predicate, out declaringTypeRef);
}
//this resolves generic eventargs (https://bugzilla.xamarin.com/show_bug.cgi?id=57574)
@ -120,8 +120,7 @@ namespace Xamarin.Forms.Build.Tasks
return bp.Single();
if (typeDef.BaseType == null || typeDef.BaseType.FullName == "System.Object")
return null;
var basetype = typeDef.BaseType.ResolveGenericParameters(typeRef);
return basetype.GetField(predicate, out declaringTypeRef);
return typeDef.BaseType.ResolveGenericParameters(typeRef).GetField(predicate, out declaringTypeRef);
}
public static bool ImplementsInterface(this TypeReference typeRef, TypeReference @interface)

Просмотреть файл

@ -11,7 +11,7 @@ using System;
namespace Xamarin.Forms
{
[AttributeUsage(AttributeTargets.Class)]
[AttributeUsage(AttributeTargets.Class, Inherited = true)]
public sealed class ContentPropertyAttribute : Attribute
{
internal static string[] ContentPropertyTypes = { "Xamarin.Forms.ContentPropertyAttribute", "System.Windows.Markup.ContentPropertyAttribute" };
@ -21,6 +21,6 @@ namespace Xamarin.Forms
Name = name;
}
public string Name { get; private set; }
public string Name { get; }
}
}

Просмотреть файл

@ -0,0 +1,11 @@
<?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="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
x:Class="Xamarin.Forms.Xaml.UnitTests.Gh3260">
<ContentPage.Content>
<local:Gh3260MyLayout x:Name="mylayout">
<Label x:Name="label"/>
</local:Gh3260MyLayout>
</ContentPage.Content>
</ContentPage>

Просмотреть файл

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Xamarin.Forms;
using Xamarin.Forms.Core.UnitTests;
namespace Xamarin.Forms.Xaml.UnitTests
{
public abstract class Gh3260MyGLayout<T> : Layout<T> where T : View
{
protected override void LayoutChildren(double x, double y, double width, double height)
{
throw new NotImplementedException();
}
}
public class Gh3260MyLayout : Gh3260MyGLayout<View>
{
protected override void LayoutChildren(double x, double y, double width, double height)
{
throw new NotImplementedException();
}
}
public partial class Gh3260 : ContentPage
{
public Gh3260()
{
InitializeComponent();
}
public Gh3260(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(false), TestCase(true)]
public void AssignContentWithNoContentAttributeDoesNotThrow(bool useCompiledXaml)
{
var layout = new Gh3260(useCompiledXaml);
Assert.That(layout.mylayout.Children.Count, Is.EqualTo(1));
Assert.That(layout.mylayout.Children[0], Is.EqualTo(layout.label));
}
}
}
}

Просмотреть файл

@ -628,6 +628,9 @@
<Compile Include="Issues\Gh3082.xaml.cs">
<DependentUpon>Gh3082.xaml</DependentUpon>
</Compile>
<Compile Include="Issues\Gh3260.xaml.cs">
<DependentUpon>Gh3260.xaml</DependentUpon>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="..\.nuspec\Xamarin.Forms.Debug.targets" Condition="'$(BuildingInsideVisualStudio)' == 'true' AND Exists('..\.nuspec\Xamarin.Forms.Build.Tasks.dll')" />
@ -1138,6 +1141,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Include="Issues\Gh3260.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />