summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Build.Tasks
diff options
context:
space:
mode:
authorStephane Delcroix <stephane@delcroix.org>2016-12-01 22:26:05 +0100
committerGitHub <noreply@github.com>2016-12-01 22:26:05 +0100
commit00b652cd43902b4499706d1f9172041c20083ae8 (patch)
tree226ef334a923b05969b410227fe69dc47f6aa9de /Xamarin.Forms.Build.Tasks
parent46c25a2edbf257153d7bb33d2ac3997a3718e3ee (diff)
downloadxamarin-forms-00b652cd43902b4499706d1f9172041c20083ae8.tar.gz
xamarin-forms-00b652cd43902b4499706d1f9172041c20083ae8.tar.bz2
xamarin-forms-00b652cd43902b4499706d1f9172041c20083ae8.zip
[Xaml] support non-int enums (#575)
Diffstat (limited to 'Xamarin.Forms.Build.Tasks')
-rw-r--r--Xamarin.Forms.Build.Tasks/NodeILExtensions.cs84
1 files changed, 71 insertions, 13 deletions
diff --git a/Xamarin.Forms.Build.Tasks/NodeILExtensions.cs b/Xamarin.Forms.Build.Tasks/NodeILExtensions.cs
index 31c1a1a8..86ef2688 100644
--- a/Xamarin.Forms.Build.Tasks/NodeILExtensions.cs
+++ b/Xamarin.Forms.Build.Tasks/NodeILExtensions.cs
@@ -111,7 +111,7 @@ namespace Xamarin.Forms.Build.Tasks
}
//Obvious Built-in conversions
if (targetTypeRef.Resolve().BaseType != null && targetTypeRef.Resolve().BaseType.FullName == "System.Enum")
- yield return Instruction.Create(OpCodes.Ldc_I4, ParseEnum(targetTypeRef, str, node));
+ yield return PushParsedEnum(targetTypeRef, str, node);
else if (targetTypeRef.FullName == "System.Char")
yield return Instruction.Create(OpCodes.Ldc_I4, Char.Parse(str));
else if (targetTypeRef.FullName == "System.SByte")
@@ -216,29 +216,87 @@ namespace Xamarin.Forms.Build.Tasks
yield return Instruction.Create(OpCodes.Box, module.Import(originalTypeRef));
}
- static int ParseEnum(TypeReference enumRef, string value, IXmlLineInfo lineInfo)
+ static Instruction PushParsedEnum(TypeReference enumRef, string value, IXmlLineInfo lineInfo)
{
var enumDef = enumRef.Resolve();
if (!enumDef.IsEnum)
throw new InvalidOperationException();
- int? result = null;
+ // The approved types for an enum are byte, sbyte, short, ushort, int, uint, long, or ulong.
+ // https://msdn.microsoft.com/en-us/library/sbbt4032.aspx
+ byte b = 0; sbyte sb = 0; short s = 0; ushort us = 0;
+ int i = 0; uint ui = 0; long l = 0; ulong ul = 0;
+ bool found = false;
+ TypeReference typeRef = null;
- foreach (var v in value.Split(','))
- {
- foreach (var field in enumDef.Fields)
- {
+ foreach (var field in enumDef.Fields)
+ if (field.Name == "value__")
+ typeRef = field.FieldType;
+
+ if (typeRef == null)
+ throw new ArgumentException();
+
+ foreach (var v in value.Split(',')) {
+ foreach (var field in enumDef.Fields) {
if (field.Name == "value__")
continue;
- if (field.Name == v.Trim())
- result = (result ?? 0) | (int)field.Constant;
+ if (field.Name == v.Trim()) {
+ switch (typeRef.FullName) {
+ case "System.Byte":
+ b |= (byte)field.Constant;
+ break;
+ case "System.SByte":
+ if (found)
+ throw new XamlParseException($"Multi-valued enums are not valid on sbyte enum types", lineInfo);
+ sb = (sbyte)field.Constant;
+ break;
+ case "System.Int16":
+ s |= (short)field.Constant;
+ break;
+ case "System.UInt16":
+ us |= (ushort)field.Constant;
+ break;
+ case "System.Int32":
+ i |= (int)field.Constant;
+ break;
+ case "System.UInt32":
+ ui |= (uint)field.Constant;
+ break;
+ case "System.Int64":
+ l |= (long)field.Constant;
+ break;
+ case "System.UInt64":
+ ul |= (ulong)field.Constant;
+ break;
+ }
+ found = true;
+ }
}
}
- if (result.HasValue)
- return result.Value;
-
- throw new XamlParseException(string.Format("Enum value not found for {0}", value), lineInfo);
+ if (!found)
+ throw new XamlParseException($"Enum value not found for {value}", lineInfo);
+
+ switch (typeRef.FullName) {
+ case "System.Byte":
+ return Instruction.Create(OpCodes.Ldc_I4, (int)b);
+ case "System.SByte":
+ return Instruction.Create(OpCodes.Ldc_I4, (int)sb);
+ case "System.Int16":
+ return Instruction.Create(OpCodes.Ldc_I4, (int)s);
+ case "System.UInt16":
+ return Instruction.Create(OpCodes.Ldc_I4, (int)us);
+ case "System.Int32":
+ return Instruction.Create(OpCodes.Ldc_I4, (int)i);
+ case "System.UInt32":
+ return Instruction.Create(OpCodes.Ldc_I4, (uint)ui);
+ case "System.Int64":
+ return Instruction.Create(OpCodes.Ldc_I4, (long)l);
+ case "System.UInt64":
+ return Instruction.Create(OpCodes.Ldc_I4, (ulong)ul);
+ default:
+ throw new XamlParseException($"Enum value not found for {value}", lineInfo);
+ }
}
public static IEnumerable<Instruction> PushXmlLineInfo(this INode node, ILContext context)