summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephane Delcroix <stephane@delcroix.org>2016-12-01 22:34:39 +0100
committerStephane Delcroix <stephane@delcroix.org>2016-12-01 23:30:14 +0100
commitb5e2ace302c0833cd6080f2aa089d56897e74ea2 (patch)
tree5a327a55bdb4b798d4bb0d9ec6b964bb1a049cd2
parent68027394ba02895e466ff41f5395e8df3666e278 (diff)
downloadxamarin-forms-b5e2ace302c0833cd6080f2aa089d56897e74ea2.tar.gz
xamarin-forms-b5e2ace302c0833cd6080f2aa089d56897e74ea2.tar.bz2
xamarin-forms-b5e2ace302c0833cd6080f2aa089d56897e74ea2.zip
[XamlC] use op_implicit where we should (#580)
* [XamlC] (passing) test for 48242 * [XamlC] (failing) test for 48242 * [XamlC] more op_implicit conversions * additional test * fix rebase
-rw-r--r--Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs18
-rw-r--r--Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs7
-rw-r--r--Xamarin.Forms.Core/ConstraintTypeConverter.cs2
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Unreported007.xaml11
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Issues/Unreported007.xaml.cs47
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/SetValue.xaml12
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/SetValue.xaml.cs62
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XStatic.xaml5
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/XStatic.xaml.cs24
-rw-r--r--Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj6
10 files changed, 187 insertions, 7 deletions
diff --git a/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
index 4523a49d..d4765511 100644
--- a/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
+++ b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
@@ -498,6 +498,10 @@ namespace Xamarin.Forms.Build.Tasks
// Worst case scenario ? InvalidCastException at runtime
if (attached && varValue.VariableType.FullName == "System.Object")
return true;
+ var implicitOperator = varValue.VariableType.GetImplicitOperatorTo(bpTypeRef, module);
+ if (implicitOperator != null)
+ return true;
+
return varValue.VariableType.InheritsFromOrImplements(bpTypeRef);
}
@@ -520,9 +524,17 @@ namespace Xamarin.Forms.Build.Tasks
foreach (var instruction in valueNode.PushConvertedValue(context, bpRef, valueNode.PushServiceProvider(context, bpRef:bpRef), true, false))
yield return instruction;
} else if (elementNode != null) {
- yield return Instruction.Create(OpCodes.Ldloc, context.Variables [elementNode]);
- if (context.Variables [elementNode].VariableType.IsValueType)
- yield return Instruction.Create(OpCodes.Box, context.Variables [elementNode].VariableType);
+ var bpTypeRef = bpRef.GetBindablePropertyType(iXmlLineInfo, module);
+ var varDef = context.Variables[elementNode];
+ var varType = varDef.VariableType;
+ var implicitOperator = varDef.VariableType.GetImplicitOperatorTo(bpTypeRef, module);
+ yield return Instruction.Create(OpCodes.Ldloc, varDef);
+ if (implicitOperator != null) {
+ yield return Instruction.Create(OpCodes.Call, module.Import(implicitOperator));
+ varType = module.Import(bpTypeRef);
+ }
+ if (varType.IsValueType)
+ yield return Instruction.Create(OpCodes.Box, varType);
}
yield return Instruction.Create(OpCodes.Callvirt, module.Import(setValue));
diff --git a/Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs b/Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs
index f0a6cef7..d0ccbc59 100644
--- a/Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs
+++ b/Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs
@@ -204,9 +204,10 @@ namespace Xamarin.Forms.Build.Tasks
}
public static MethodReference GetImplicitOperatorTo(this TypeReference fromType, TypeReference toType, ModuleDefinition module)
- {
- var implicitOperators = fromType.GetMethods(md => md.IsPublic && md.IsStatic && md.IsSpecialName && md.Name == "op_Implicit",
- module).ToList();
+ {
+ var implicitOperatorsOnFromType = fromType.GetMethods(md => md.IsPublic && md.IsStatic && md.IsSpecialName && md.Name == "op_Implicit", module);
+ var implicitOperatorsOnToType = toType.GetMethods(md => md.IsPublic && md.IsStatic && md.IsSpecialName && md.Name == "op_Implicit", module);
+ var implicitOperators = implicitOperatorsOnFromType.Concat(implicitOperatorsOnToType).ToList();
if (implicitOperators.Any()) {
foreach (var op in implicitOperators) {
var cast = op.Item1;
diff --git a/Xamarin.Forms.Core/ConstraintTypeConverter.cs b/Xamarin.Forms.Core/ConstraintTypeConverter.cs
index 8cc45229..fb0be513 100644
--- a/Xamarin.Forms.Core/ConstraintTypeConverter.cs
+++ b/Xamarin.Forms.Core/ConstraintTypeConverter.cs
@@ -11,7 +11,7 @@ namespace Xamarin.Forms
if (value != null && double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out size))
return Constraint.Constant(size);
- throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(Color)));
+ throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", value, typeof(Constraint)));
}
}
} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported007.xaml b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported007.xaml
new file mode 100644
index 00000000..4132f908
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported007.xaml
@@ -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"
+ x:Class="Xamarin.Forms.Xaml.UnitTests.Unreported007">
+
+ <Label Text="Foo" x:Name="label">
+ <RelativeLayout.XConstraint>
+ <OnPlatform x:TypeArguments="Constraint" Android="{ConstraintExpression Type=Constant,Constant=6}" iOS="{ConstraintExpression Type=Constant,Constant=3}" />
+ </RelativeLayout.XConstraint>
+ </Label>
+</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported007.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported007.xaml.cs
new file mode 100644
index 00000000..279deed4
--- /dev/null
+++ b/Xamarin.Forms.Xaml.UnitTests/Issues/Unreported007.xaml.cs
@@ -0,0 +1,47 @@
+´╗┐using System;
+using System.Collections.Generic;
+using NUnit.Framework;
+using Xamarin.Forms;
+using Xamarin.Forms.Core.UnitTests;
+
+namespace Xamarin.Forms.Xaml.UnitTests
+{
+ public partial class Unreported007 : ContentPage
+ {
+ public Unreported007()
+ {
+ InitializeComponent();
+ }
+ public Unreported007(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 ConstraintsAreEvaluatedWithOnPlatform(bool useCompiledXaml)
+ {
+ if (useCompiledXaml)
+ MockCompiler.Compile(typeof(Unreported007));
+ Device.OS = TargetPlatform.iOS;
+ var page = new Unreported007(useCompiledXaml);
+ Assert.That(RelativeLayout.GetXConstraint(page.label), Is.TypeOf<Constraint>());
+ Assert.AreEqual(3, RelativeLayout.GetXConstraint(page.label).Compute(null));
+ }
+ }
+ }
+}
diff --git a/Xamarin.Forms.Xaml.UnitTests/SetValue.xaml b/Xamarin.Forms.Xaml.UnitTests/SetValue.xaml
index 40cf6210..61451223 100644
--- a/Xamarin.Forms.Xaml.UnitTests/SetValue.xaml
+++ b/Xamarin.Forms.Xaml.UnitTests/SetValue.xaml
@@ -84,5 +84,17 @@
</ContentView.Content>
</ContentView>
<local:ViewWithEnums x:Name="enums" IntEnum="Foo" ByteEnum="Bar" />
+ <local:MockViewWithValues x:Name="implicit0">
+ <local:MockViewWithValues.BPBar>
+ <local:SV_Foo Value="Bar"/>
+ </local:MockViewWithValues.BPBar>
+ </local:MockViewWithValues>
+ <!--<local:MockViewWithValues x:Name="implicit1" BPFoo="Foo" />-->
+ <local:MockViewWithValues x:Name="implicit2">
+ <local:MockViewWithValues.Bar>
+ <local:SV_Foo Value="Bar"/>
+ </local:MockViewWithValues.Bar>
+ </local:MockViewWithValues>
+ <!--<local:MockViewWithValues x:Name="implicit3" Foo="Foo" />-->
</StackLayout>
</ContentPage>
diff --git a/Xamarin.Forms.Xaml.UnitTests/SetValue.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/SetValue.xaml.cs
index 963fca06..b6395a7f 100644
--- a/Xamarin.Forms.Xaml.UnitTests/SetValue.xaml.cs
+++ b/Xamarin.Forms.Xaml.UnitTests/SetValue.xaml.cs
@@ -17,6 +17,38 @@ namespace Xamarin.Forms.Xaml.UnitTests
{
public UInt16 UShort { get; set; }
public decimal ADecimal { get; set; }
+ public SV_Foo Foo { get; set; }
+ public string Bar { get; set; }
+
+ public static readonly BindableProperty BPFooProperty =
+ BindableProperty.Create("BPFoo", typeof(SV_Foo), typeof(MockViewWithValues), default(SV_Foo));
+
+ public SV_Foo BPFoo {
+ get { throw new NotImplementedException(); }
+ set { throw new NotImplementedException(); }
+ }
+
+ public static readonly BindableProperty BPBarProperty =
+ BindableProperty.Create("BPBar", typeof(string), typeof(MockViewWithValues), default(string));
+
+ public string BPBar {
+ get { throw new NotImplementedException(); }
+ set { throw new NotImplementedException(); }
+ }
+ }
+
+ public class SV_Foo
+ {
+ public string Value { get; set; }
+ public static implicit operator SV_Foo(string value)
+ {
+ return new SV_Foo { Value = value };
+ }
+
+ public static implicit operator string(SV_Foo foo)
+ {
+ return foo.Value;
+ }
}
public enum IntEnum
@@ -254,6 +286,36 @@ namespace Xamarin.Forms.Xaml.UnitTests
Assert.AreEqual(IntEnum.Foo, page.enums.IntEnum);
Assert.AreEqual(ByteEnum.Bar, page.enums.ByteEnum);
}
+
+ public void SetValueWithImplicitOperatorOnSource(bool useCompiledXaml)
+ {
+ var page = new SetValue(useCompiledXaml);
+ Assert.AreEqual("Bar", page.implicit0.GetValue(MockViewWithValues.BPBarProperty));
+ }
+
+ //[TestCase(false)]
+ //[TestCase(true)]
+ //public void SetValueWithImplicitOperatorOnTarget(bool useCompiledXaml)
+ //{
+ // var page = new SetValue(useCompiledXaml);
+ // Assert.AreEqual("Foo", ((SV_Foo)page.implicit1.GetValue(MockViewWithValues.BPFooProperty)).Value);
+ //}
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void SetWithImplicitOperatorOnSource(bool useCompiledXaml)
+ {
+ var page = new SetValue(useCompiledXaml);
+ Assert.AreEqual("Bar", page.implicit2.Bar);
+ }
+
+ //[TestCase(false)]
+ //[TestCase(true)]
+ //public void SetWithImplicitOperatorOnTarget(bool useCompiledXaml)
+ //{
+ // var page = new SetValue(useCompiledXaml);
+ // Assert.AreEqual("Foo", page.implicit3.Foo.Value);
+ //}
}
}
}
diff --git a/Xamarin.Forms.Xaml.UnitTests/XStatic.xaml b/Xamarin.Forms.Xaml.UnitTests/XStatic.xaml
index 32d2945e..cf68525b 100644
--- a/Xamarin.Forms.Xaml.UnitTests/XStatic.xaml
+++ b/Xamarin.Forms.Xaml.UnitTests/XStatic.xaml
@@ -3,6 +3,9 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Xamarin.Forms.Xaml.UnitTests"
x:Class="Xamarin.Forms.Xaml.UnitTests.XStatic">
+ <ContentPage.ToolbarItems>
+ <ToolbarItem Icon="{x:Static local:MockxStatic.MockFieldRef}" />
+ </ContentPage.ToolbarItems>
<StackLayout>
<Label x:Name="staticproperty"
Text="{x:Static Member=local:MockxStatic.MockStaticProperty}" />
@@ -16,5 +19,7 @@
Text="{x:Static local:MockxStatic.MockField}"/>
<ScrollView x:Name="enuM"
Orientation="{x:Static ScrollOrientation.Both}"/>
+ <Label x:Name="field2"
+ Text="{x:Static local:MockxStatic.MockFieldRef}" />
</StackLayout>
</ContentPage> \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/XStatic.xaml.cs b/Xamarin.Forms.Xaml.UnitTests/XStatic.xaml.cs
index d8a466e9..19c62630 100644
--- a/Xamarin.Forms.Xaml.UnitTests/XStatic.xaml.cs
+++ b/Xamarin.Forms.Xaml.UnitTests/XStatic.xaml.cs
@@ -3,11 +3,18 @@ using Xamarin.Forms.Core.UnitTests;
namespace Xamarin.Forms.Xaml.UnitTests
{
+
+ public class Icons
+ {
+ public const string CLOSE = "ic_close.png";
+ }
+
public class MockxStatic
{
public static string MockStaticProperty { get { return "Property"; } }
public const string MockConstant = "Constant";
public static string MockField = "Field";
+ public static string MockFieldRef = Icons.CLOSE;
public string InstanceProperty { get { return "InstanceProperty"; } }
public static readonly Color BackgroundColor = Color.Fuchsia;
}
@@ -102,6 +109,23 @@ namespace Xamarin.Forms.Xaml.UnitTests
var layout = new XStatic(useCompiledXaml);
Assert.AreEqual(ScrollOrientation.Both, layout.enuM.Orientation);
}
+
+ [TestCase(false)]
+ [TestCase(true)]
+ public void FieldRef(bool useCompiledXaml)
+ {
+ var layout = new XStatic(useCompiledXaml);
+ Assert.AreEqual("ic_close.png", layout.field2.Text);
+ }
+
+ [TestCase(false)]
+ [TestCase(true)]
+ // https://bugzilla.xamarin.com/show_bug.cgi?id=48242
+ public void xStaticAndImplicitOperators(bool useCompiledXaml)
+ {
+ var layout = new XStatic(useCompiledXaml);
+ Assert.AreEqual("ic_close.png", layout.ToolbarItems[0].Icon.File);
+ }
}
}
} \ No newline at end of file
diff --git a/Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj b/Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj
index 582103bf..7096e520 100644
--- a/Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj
+++ b/Xamarin.Forms.Xaml.UnitTests/Xamarin.Forms.Xaml.UnitTests.csproj
@@ -383,6 +383,9 @@
<Compile Include="Issues\Bz48554.xaml.cs">
<DependentUpon>Bz48554.xaml</DependentUpon>
</Compile>
+ <Compile Include="Issues\Unreported007.xaml.cs">
+ <DependentUpon>Unreported007.xaml</DependentUpon>
+ </Compile>
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="..\.nuspec\Xamarin.Forms.Debug.targets" />
@@ -683,6 +686,9 @@
<EmbeddedResource Include="Issues\Bz48554.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
+ <EmbeddedResource Include="Issues\Unreported007.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />