summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Build.Tasks
diff options
context:
space:
mode:
authorStephane Delcroix <stephane@delcroix.org>2016-08-02 22:24:50 +0200
committerJason Smith <jason.smith@xamarin.com>2016-08-02 13:24:50 -0700
commit89199205e48fe3fdf4336fe7e0f8af7dc0b662de (patch)
tree42e4d3a8f53ecd45d95b290bcdedd809eb046e4c /Xamarin.Forms.Build.Tasks
parentac44cf9dec53b3b8be1836f20479f01820f3667f (diff)
downloadxamarin-forms-89199205e48fe3fdf4336fe7e0f8af7dc0b662de.tar.gz
xamarin-forms-89199205e48fe3fdf4336fe7e0f8af7dc0b662de.tar.bz2
xamarin-forms-89199205e48fe3fdf4336fe7e0f8af7dc0b662de.zip
Xaml convert on add (#273)
* [Xaml] add test for conversion on Set and Add * [Xaml] Fix conversion on Add() * [XamlC] use op_implicit before Add()
Diffstat (limited to 'Xamarin.Forms.Build.Tasks')
-rw-r--r--Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs80
-rw-r--r--Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs21
2 files changed, 57 insertions, 44 deletions
diff --git a/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
index 16eddb41..a1c0711a 100644
--- a/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
+++ b/Xamarin.Forms.Build.Tasks/SetPropertiesVisitor.cs
@@ -141,10 +141,10 @@ namespace Xamarin.Forms.Build.Tasks
}
else if (IsCollectionItem(node, parentNode) && parentNode is ListNode)
{
- // IL_000d: ldloc.2
- // IL_000e: callvirt instance class [mscorlib]System.Collections.Generic.IList`1<!0> class [Xamarin.Forms.Core]Xamarin.Forms.Layout`1<class [Xamarin.Forms.Core]Xamarin.Forms.View>::get_Children()
- // IL_0013: ldloc.0
- // IL_0014: callvirt instance void class [mscorlib]System.Collections.Generic.ICollection`1<class [Xamarin.Forms.Core]Xamarin.Forms.View>::Add(!0)
+// IL_000d: ldloc.2
+// IL_000e: callvirt instance class [mscorlib]System.Collections.Generic.IList`1<!0> class [Xamarin.Forms.Core]Xamarin.Forms.Layout`1<class [Xamarin.Forms.Core]Xamarin.Forms.View>::get_Children()
+// IL_0013: ldloc.0
+// IL_0014: callvirt instance void class [mscorlib]System.Collections.Generic.ICollection`1<class [Xamarin.Forms.Core]Xamarin.Forms.View>::Add(!0)
var parentList = (ListNode)parentNode;
var parent = Context.Variables[((IElementNode)parentNode.Parent)];
@@ -314,16 +314,16 @@ namespace Xamarin.Forms.Build.Tasks
GetNameAndTypeRef(ref elementType, propertyName.NamespaceURI, ref localName, context, iXmlLineInfo);
//If the target is an event, connect
- // IL_0007: ldloc.0
- // IL_0008: ldarg.0
- //
- // IL_0009: ldftn instance void class Xamarin.Forms.Xaml.XamlcTests.MyPage::OnButtonClicked(object, class [mscorlib]System.EventArgs)
+// IL_0007: ldloc.0
+// IL_0008: ldarg.0
+//
+// IL_0009: ldftn instance void class Xamarin.Forms.Xaml.XamlcTests.MyPage::OnButtonClicked(object, class [mscorlib]System.EventArgs)
//OR, if the handler is virtual
- // IL_000x: ldarg.0
- // IL_0009: ldvirtftn instance void class Xamarin.Forms.Xaml.XamlcTests.MyPage::OnButtonClicked(object, class [mscorlib]System.EventArgs)
- //
- // IL_000f: newobj instance void class [mscorlib]System.EventHandler::'.ctor'(object, native int)
- // IL_0014: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.Button::add_Clicked(class [mscorlib]System.EventHandler)
+// IL_000x: ldarg.0
+// IL_0009: ldvirtftn instance void class Xamarin.Forms.Xaml.XamlcTests.MyPage::OnButtonClicked(object, class [mscorlib]System.EventArgs)
+//
+// IL_000f: newobj instance void class [mscorlib]System.EventHandler::'.ctor'(object, native int)
+// IL_0014: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.Button::add_Clicked(class [mscorlib]System.EventHandler)
var eventinfo = elementType.GetEvent(ed => ed.Name == localName);
if (eventinfo != null)
@@ -409,10 +409,10 @@ namespace Xamarin.Forms.Build.Tasks
}
//If it's a BP, SetValue ()
- // IL_0007: ldloc.0
- // IL_0008: ldsfld class [Xamarin.Forms.Core]Xamarin.Forms.BindableProperty [Xamarin.Forms.Core]Xamarin.Forms.Label::TextProperty
- // IL_000d: ldstr "foo"
- // IL_0012: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.BindableObject::SetValue(class [Xamarin.Forms.Core]Xamarin.Forms.BindableProperty, object)
+// IL_0007: ldloc.0
+// IL_0008: ldsfld class [Xamarin.Forms.Core]Xamarin.Forms.BindableProperty [Xamarin.Forms.Core]Xamarin.Forms.Label::TextProperty
+// IL_000d: ldstr "foo"
+// IL_0012: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.BindableObject::SetValue(class [Xamarin.Forms.Core]Xamarin.Forms.BindableProperty, object)
if (bpRef != null)
{
//TODO: check if parent is a BP
@@ -454,9 +454,9 @@ namespace Xamarin.Forms.Build.Tasks
}
//If it's a property, set it
- // IL_0007: ldloc.0
- // IL_0008: ldstr "foo"
- // IL_000d: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.Label::set_Text(string)
+// IL_0007: ldloc.0
+// IL_0008: ldstr "foo"
+// IL_000d: callvirt instance void class [Xamarin.Forms.Core]Xamarin.Forms.Label::set_Text(string)
PropertyDefinition property = elementType.GetProperty(pd => pd.Name == localName, out declaringTypeReference);
MethodDefinition propertySetter;
if (property != null && (propertySetter = property.SetMethod) != null && propertySetter.IsPublic)
@@ -483,28 +483,7 @@ namespace Xamarin.Forms.Build.Tasks
if (valueNode is IElementNode)
{
var vardef = context.Variables[(ElementNode)valueNode];
- var implicitOperators =
- vardef.VariableType.GetMethods(md => md.IsPublic && md.IsStatic && md.IsSpecialName && md.Name == "op_Implicit",
- module).ToList();
- MethodReference implicitOperator = null;
- if (implicitOperators.Any())
- {
- foreach (var op in implicitOperators)
- {
- var cast = op.Item1;
- var opDeclTypeRef = op.Item2;
- var castDef = module.Import(cast).ResolveGenericParameters(opDeclTypeRef, module);
- var returnType = castDef.ReturnType;
- if (returnType.IsGenericParameter)
- returnType = ((GenericInstanceType)opDeclTypeRef).GenericArguments[((GenericParameter)returnType).Position];
- if (returnType.FullName == propertyType.FullName &&
- cast.Parameters[0].ParameterType.Name == vardef.VariableType.Name)
- {
- implicitOperator = castDef;
- break;
- }
- }
- }
+ var implicitOperator = vardef.VariableType.GetImplicitOperatorTo(propertyType, module);
//TODO replace latest check by a runtime type check
if (implicitOperator != null || vardef.VariableType.InheritsFromOrImplements(propertyType) ||
@@ -514,7 +493,7 @@ namespace Xamarin.Forms.Build.Tasks
context.IL.Emit(OpCodes.Ldloc, vardef);
if (implicitOperator != null)
{
- // IL_000f: call !0 class [Xamarin.Forms.Core]Xamarin.Forms.OnPlatform`1<bool>::op_Implicit(class [Xamarin.Forms.Core]Xamarin.Forms.OnPlatform`1<!0>)
+// IL_000f: call !0 class [Xamarin.Forms.Core]Xamarin.Forms.OnPlatform`1<bool>::op_Implicit(class [Xamarin.Forms.Core]Xamarin.Forms.OnPlatform`1<!0>)
context.IL.Emit(OpCodes.Call, module.Import(implicitOperator));
}
else if (!vardef.VariableType.IsValueType && propertyType.IsValueType)
@@ -537,6 +516,7 @@ namespace Xamarin.Forms.Build.Tasks
var propertyGetterRef = module.Import(propertyGetter);
propertyGetterRef = module.Import(propertyGetterRef.ResolveGenericParameters(declaringTypeReference, module));
var propertyType = propertyGetterRef.ReturnType.ResolveGenericParameters(declaringTypeReference);
+ var vardef = context.Variables [(ElementNode)valueNode];
//TODO check md.Parameters[0] type
var adderTuple =
@@ -545,12 +525,16 @@ namespace Xamarin.Forms.Build.Tasks
{
var adderRef = module.Import(adderTuple.Item1);
adderRef = module.Import(adderRef.ResolveGenericParameters(adderTuple.Item2, module));
+ var childType = GetParameterType(adderRef.Parameters [0]);
+ var implicitOperator = vardef.VariableType.GetImplicitOperatorTo(childType, module);
if (valueNode is IElementNode)
{
context.IL.Emit(OpCodes.Ldloc, parent);
context.IL.Emit(OpCodes.Callvirt, propertyGetterRef);
- context.IL.Emit(OpCodes.Ldloc, context.Variables[(ElementNode)valueNode]);
+ context.IL.Emit(OpCodes.Ldloc, vardef);
+ if (implicitOperator != null)
+ context.IL.Emit(OpCodes.Call, module.Import(implicitOperator));
context.IL.Emit(OpCodes.Callvirt, adderRef);
if (adderRef.ReturnType.FullName != "System.Void")
context.IL.Emit(OpCodes.Pop);
@@ -567,6 +551,14 @@ namespace Xamarin.Forms.Build.Tasks
context.IL.Append(br);
}
+ public static TypeReference GetParameterType(ParameterDefinition param)
+ {
+ if (!param.ParameterType.IsGenericParameter)
+ return param.ParameterType;
+ var type = (param.Method as MethodReference).DeclaringType as GenericInstanceType;
+ return type.GenericArguments [0];
+ }
+
static bool GetNameAndTypeRef(ref TypeReference elementType, string namespaceURI, ref string localname,
ILContext context, IXmlLineInfo lineInfo)
{
diff --git a/Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs b/Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs
index 89a31765..60e52c80 100644
--- a/Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs
+++ b/Xamarin.Forms.Build.Tasks/TypeReferenceExtensions.cs
@@ -200,6 +200,27 @@ namespace Xamarin.Forms.Build.Tasks
yield return tuple;
}
+ 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();
+ if (implicitOperators.Any()) {
+ foreach (var op in implicitOperators) {
+ var cast = op.Item1;
+ var opDeclTypeRef = op.Item2;
+ var castDef = module.Import(cast).ResolveGenericParameters(opDeclTypeRef, module);
+ var returnType = castDef.ReturnType;
+ if (returnType.IsGenericParameter)
+ returnType = ((GenericInstanceType)opDeclTypeRef).GenericArguments [((GenericParameter)returnType).Position];
+ if (returnType.FullName == toType.FullName &&
+ cast.Parameters [0].ParameterType.Name == fromType.Name) {
+ return castDef;
+ }
+ }
+ }
+ return null;
+ }
+
public static TypeReference ResolveGenericParameters(this TypeReference self, TypeReference declaringTypeReference)
{
var genericself = self as GenericInstanceType;