New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[XamlC] support setting values on ValueTypes #596

Merged
merged 1 commit into from Dec 12, 2016
Jump to file or symbol
Failed to load files and symbols.
+104 −3
Diff settings

Always

Just for now

@@ -953,12 +953,19 @@ static IEnumerable<Instruction> Set(VariableDefinition parent, string localName,
var valueNode = node as ValueNode;
var elementNode = node as IElementNode;
yield return Instruction.Create(OpCodes.Ldloc, parent);
//if it's a value type, load the address so we can invoke methods on it
if (parent.VariableType.IsValueType)
yield return Instruction.Create(OpCodes.Ldloca, parent);
else
yield return Instruction.Create(OpCodes.Ldloc, parent);
if (valueNode != null) {
foreach (var instruction in valueNode.PushConvertedValue(context, propertyType, new ICustomAttributeProvider [] { property, propertyType.Resolve() }, valueNode.PushServiceProvider(context, propertyRef:property), false, true))
yield return instruction;
yield return Instruction.Create(OpCodes.Callvirt, propertySetterRef);
if (parent.VariableType.IsValueType)
yield return Instruction.Create(OpCodes.Call, propertySetterRef);
else
yield return Instruction.Create(OpCodes.Callvirt, propertySetterRef);
} else if (elementNode != null) {
var vardef = context.Variables [elementNode];
var implicitOperator = vardef.VariableType.GetImplicitOperatorTo(propertyType, module);
@@ -970,7 +977,10 @@ static IEnumerable<Instruction> Set(VariableDefinition parent, string localName,
yield return Instruction.Create(OpCodes.Unbox_Any, module.Import(propertyType));
else if (vardef.VariableType.IsValueType && propertyType.FullName == "System.Object")
yield return Instruction.Create(OpCodes.Box, vardef.VariableType);
yield return Instruction.Create(OpCodes.Callvirt, propertySetterRef);
if (parent.VariableType.IsValueType)
yield return Instruction.Create(OpCodes.Call, propertySetterRef);
else
yield return Instruction.Create(OpCodes.Callvirt, propertySetterRef);

This comment has been minimized.

@StephaneDelcroix

StephaneDelcroix Dec 9, 2016

Member

setting properties on valuetypes require to load their address (ldloca) and doesn't support virtual calls.

@StephaneDelcroix

StephaneDelcroix Dec 9, 2016

Member

setting properties on valuetypes require to load their address (ldloca) and doesn't support virtual calls.

}
}
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Xamarin.Forms.Xaml.UnitTests.Bz46921">
<ContentPage.Resources>
<ResourceDictionary>
<Thickness x:Key="thickness0">4,20,4,20</Thickness>
<Thickness
x:Key="thickness1"
Left="4"
Top="20"
Bottom="20"
Right="4"/>
<Thickness x:Key="thickness2">
<Thickness.Left>
4
</Thickness.Left>
<Thickness.Top>
20
</Thickness.Top>
<Thickness.Bottom>
20
</Thickness.Bottom>
<Thickness.Right>
4
</Thickness.Right>
</Thickness>
<Thickness x:Key="thickness3">
<Thickness.Left>
<x:Double>4</x:Double>
</Thickness.Left>
<Thickness.Top>
<x:Double>20</x:Double>
</Thickness.Top>
<Thickness.Bottom>
<x:Double>20</x:Double>
</Thickness.Bottom>
<Thickness.Right>
<x:Double>4</x:Double>
</Thickness.Right>
</Thickness>
</ResourceDictionary>
</ContentPage.Resources>
</ContentPage>
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using Xamarin.Forms;
namespace Xamarin.Forms.Xaml.UnitTests
{
public partial class Bz46921 : ContentPage
{
public Bz46921()
{
InitializeComponent();
}
public Bz46921(bool useCompiledXaml)
{
//this stub will be replaced at compile time
}
[TestFixture]
class Tests
{
[TestCase(true)]
[TestCase(false)]
public void MultipleWaysToCreateAThicknessResource(bool useCompiledXaml)
{
var page = new Bz46921(useCompiledXaml);
foreach (var resname in new string[] { "thickness0", "thickness1", "thickness2", "thickness3", }) {
var resource = page.Resources[resname];
Assert.That(resource, Is.TypeOf<Thickness>());
var thickness = (Thickness)resource;
Assert.AreEqual(new Thickness(4, 20, 4, 20), thickness);
}
}
}
}
}
@@ -397,6 +397,9 @@
<DependentUpon>FactoryMethodMissingMethod.xaml</DependentUpon>
</Compile>
<Compile Include="XamlC\TypeReferenceExtensionsTests.cs" />
<Compile Include="Issues\Bz46921.xaml.cs">
<DependentUpon>Bz46921.xaml</DependentUpon>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="..\.nuspec\Xamarin.Forms.Debug.targets" />
@@ -715,6 +718,9 @@
<EmbeddedResource Include="FactoryMethodMissingMethod.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Include="Issues\Bz46921.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
ProTip! Use n and p to navigate between commits in a pull request.