Skip to content
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

[X] Add compiled converters #7245

Merged
merged 2 commits into from May 23, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view

This file was deleted.

@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using Microsoft.Maui.Controls.Build.Tasks;
using Microsoft.Maui.Controls.Xaml;
using Mono.Cecil.Cil;

namespace Microsoft.Maui.Controls.XamlC
{
class EnumTypeConverter<TEnum> : ICompiledTypeConverter where TEnum: struct
{
public IEnumerable<Instruction> ConvertFromString(string value, ILContext context, BaseNode node)
{
if (!string.IsNullOrEmpty(value))
{
value = value.Trim();
if (Enum.TryParse(value, out TEnum enumValue))
{
yield return Instruction.Create(OpCodes.Ldc_I4, (int)(object)enumValue);
yield break;
}
}
throw new BuildException(BuildExceptionCode.Conversion, node, null, value, typeof(TEnum));
}
}
}
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using Microsoft.Maui.Controls.Build.Tasks;
using Microsoft.Maui.Controls.Xaml;
using Microsoft.Maui.Layouts;
using Mono.Cecil.Cil;

namespace Microsoft.Maui.Controls.XamlC
{
class FlexBasisTypeConverter : ICompiledTypeConverter
{
public IEnumerable<Instruction> ConvertFromString(string value, ILContext context, BaseNode node)
{
var module = context.Body.Method.Module;
if (!string.IsNullOrEmpty(value))
{
value = value.Trim();
if (value == "Auto")
StephaneDelcroix marked this conversation as resolved.
Show resolved Hide resolved
{
yield return Instruction.Create(OpCodes.Ldsfld,
module.ImportFieldReference(("Microsoft.Maui", "Microsoft.Maui.Layouts", "FlexBasis"),
"Auto",
isStatic: true));
yield break;
}
if (value.EndsWith("%", StringComparison.OrdinalIgnoreCase)
&& float.TryParse(value.Substring(0, value.Length - 1), NumberStyles.Number, CultureInfo.InvariantCulture, out float relflex))
{
yield return Instruction.Create(OpCodes.Ldc_R4, (float)(relflex / 100));
yield return Instruction.Create(OpCodes.Ldc_I4_1); //isRelative: true
yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui", "Microsoft.Maui.Layouts", "FlexBasis"), parameterTypes: new[] {
("mscorlib", "System", "Single"),
("mscorlib", "System", "Boolean")}));
yield break;
}
if (float.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out float flex))
{
yield return Instruction.Create(OpCodes.Ldc_R4, flex);
yield return Instruction.Create(OpCodes.Ldc_I4_0); //isRelative: false
yield return Instruction.Create(OpCodes.Newobj, module.ImportCtorReference(("Microsoft.Maui", "Microsoft.Maui.Layouts", "FlexBasis"), parameterTypes: new[] {
("mscorlib", "System", "Single"),
("mscorlib", "System", "Boolean")}));
yield break;
}
}
throw new BuildException(BuildExceptionCode.Conversion, node, null, value, typeof(FlexBasis));
}
}
}
@@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.Maui.Controls.Build.Tasks;
using Microsoft.Maui.Controls.Xaml;
using Mono.Cecil;
using Mono.Cecil.Cil;

namespace Microsoft.Maui.Controls.XamlC
Expand All @@ -25,7 +23,7 @@ public IEnumerable<Instruction> ConvertFromString(string value, ILContext contex
}

#pragma warning disable CS0612 // Type or member is obsolete
if (Enum.TryParse<NamedSize>(value, out NamedSize namedSize))
if (Enum.TryParse(value, out NamedSize namedSize))
{
//Device.GetNamedSize(namedSize, targetObject.GetType())
yield return Instruction.Create(OpCodes.Ldc_I4, (int)namedSize);
Expand Down
14 changes: 12 additions & 2 deletions src/Controls/src/Build.Tasks/NodeILExtensions.cs
Expand Up @@ -155,14 +155,24 @@ static T TryFormat<T>(Func<string, T> func, IXmlLineInfo lineInfo, string str)
{ module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "ThicknessTypeConverter")), typeof(ThicknessTypeConverter) },
{ module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "CornerRadiusTypeConverter")), typeof(CornerRadiusTypeConverter) },
{ module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "EasingTypeConverter")), typeof(EasingTypeConverter) },
{ module.ImportReference(("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics.Converters", "ColorTypeConverter")), typeof(ColorTypeConverter) }
{ module.ImportReference(("Microsoft.Maui.Graphics", "Microsoft.Maui.Graphics.Converters", "ColorTypeConverter")), typeof(ColorTypeConverter) },
{ module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexJustifyTypeConverter")), typeof(EnumTypeConverter<Layouts.FlexJustify>) },
{ module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexDirectionTypeConverter")), typeof(EnumTypeConverter<Layouts.FlexDirection>) },
{ module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexAlignContentTypeConverter")), typeof(EnumTypeConverter<Layouts.FlexAlignContent>) },
{ module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexAlignItemsTypeConverter")), typeof(EnumTypeConverter<Layouts.FlexAlignItems>) },
{ module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexAlignSelfTypeConverter")), typeof(EnumTypeConverter<Layouts.FlexAlignSelf>) },
{ module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexWrapTypeConverter")), typeof(EnumTypeConverter<Layouts.FlexWrap>) },
{ module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "FlexBasisTypeConverter")), typeof(FlexBasisTypeConverter) },
{ module.ImportReference(("Microsoft.Maui", "Microsoft.Maui.Converters", "FlowDirectionTypeConverter")), typeof(EnumTypeConverter<FlowDirection>) },

};
}

var str = (string)node.Value;
//If the TypeConverter has a ProvideCompiledAttribute that can be resolved, shortcut this
Type compiledConverterType;
if (typeConverter?.GetCustomAttribute(module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "ProvideCompiledAttribute"))?.ConstructorArguments?.First().Value is string compiledConverterName && (compiledConverterType = Type.GetType(compiledConverterName)) != null
if ( typeConverter?.GetCustomAttribute(module, ("Microsoft.Maui.Controls", "Microsoft.Maui.Controls.Xaml", "ProvideCompiledAttribute"))?.ConstructorArguments?.First().Value is string compiledConverterName
&& (compiledConverterType = Type.GetType(compiledConverterName)) != null
|| (typeConverter != null && KnownCompiledTypeConverters.TryGetValue(typeConverter, out compiledConverterType)))
{
var compiledConverter = Activator.CreateInstance(compiledConverterType);
Expand Down
4 changes: 2 additions & 2 deletions src/Controls/src/Core.Design/AttributeTableBuilder.cs
Expand Up @@ -30,7 +30,7 @@ public AttributeTableBuilder()
AddMemberAttributes("Microsoft.Maui.Controls.VisualElement", "Visual",
new TypeConverterAttribute(typeof(VisualDesignTypeConverter)));

AddMemberAttributes("Microsoft.Maui.Controls.VisualElement", "FlowDirection",
AddTypeAttributes("Microsoft.Maui.FlowDirection",
new TypeConverterAttribute(typeof(FlowDirectionDesignTypeConverter)));

AddMemberAttributes("Microsoft.Maui.Controls.ItemsView", "ItemsLayout",
Expand Down Expand Up @@ -95,4 +95,4 @@ private void AddTypeAttributes(string typeName, params Attribute[] attribs)
private void AddMemberAttributes(string typeName, string memberName, params Attribute[] attribs)
=> AddCallback(typeName, builder => builder.AddCustomAttributes(memberName, attribs));
}
}
}
1 change: 0 additions & 1 deletion src/Controls/src/Core/VisualElement.cs
Expand Up @@ -332,7 +332,6 @@ void InvalidateGradientBrushRequested(object sender, EventArgs e)
IFlowDirectionController FlowController => this;

/// <include file="../../docs/Microsoft.Maui.Controls/VisualElement.xml" path="//Member[@MemberName='FlowDirection']/Docs" />
[System.ComponentModel.TypeConverter(typeof(FlowDirectionConverter))]
public FlowDirection FlowDirection
{
get { return (FlowDirection)GetValue(FlowDirectionProperty); }
Expand Down
1 change: 0 additions & 1 deletion src/Controls/src/Xaml/ApplyPropertiesVisitor.cs
Expand Up @@ -377,7 +377,6 @@ public static void SetPropertyValue(object xamlelement, XmlName propertyName, ob
context.ExceptionHandler(xpe);
else
throw xpe;

}

//Used by HotReload, do not change signature
Expand Down
2 changes: 1 addition & 1 deletion src/Core/src/Converters/FlexEnumsConverters.cs
Expand Up @@ -218,9 +218,9 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c
var strValue = value?.ToString();
if (strValue != null)
{
strValue = strValue.Trim();
if (strValue.Equals("auto", StringComparison.OrdinalIgnoreCase))
return FlexBasis.Auto;
value = strValue.Trim();
if (strValue.EndsWith("%", StringComparison.OrdinalIgnoreCase) && float.TryParse(strValue.Substring(0, strValue.Length - 1), NumberStyles.Number, CultureInfo.InvariantCulture, out float relflex))
return new FlexBasis(relflex / 100, isRelative: true);
if (float.TryParse(strValue, NumberStyles.Number, CultureInfo.InvariantCulture, out float flex))
Expand Down
Expand Up @@ -2,20 +2,17 @@
using System.ComponentModel;
using System.Globalization;

namespace Microsoft.Maui.Controls
#nullable disable
namespace Microsoft.Maui.Converters
{
/// <include file="../../docs/Microsoft.Maui.Controls/FlowDirectionConverter.xml" path="Type[@FullName='Microsoft.Maui.Controls.FlowDirectionConverter']/Docs" />
public class FlowDirectionConverter : TypeConverter
public class FlowDirectionTypeConverter : TypeConverter
{
/// <include file="../../docs/Microsoft.Maui.Controls/FlowDirectionConverter.xml" path="//Member[@MemberName='CanConvertFrom']/Docs" />
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
=> sourceType == typeof(string);

/// <include file="../../docs/Microsoft.Maui.Controls/FlowDirectionConverter.xml" path="//Member[@MemberName='CanConvertTo']/Docs" />
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
=> destinationType == typeof(string);

/// <include file="../../docs/Microsoft.Maui.Controls/FlowDirectionConverter.xml" path="//Member[@MemberName='ConvertFrom']/Docs" />
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var strValue = value?.ToString();
Expand All @@ -32,10 +29,9 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c
if (strValue.Equals("inherit", StringComparison.OrdinalIgnoreCase))
return FlowDirection.MatchParent;
}
throw new InvalidOperationException(string.Format("Cannot convert \"{0}\" into {1}", strValue, typeof(FlowDirection)));
throw new InvalidOperationException($"Cannot convert \"{strValue}\" into {typeof(FlowDirection)}");
}

/// <include file="../../docs/Microsoft.Maui.Controls/FlowDirectionConverter.xml" path="//Member[@MemberName='ConvertTo']/Docs" />
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (value is not FlowDirection direction)
Expand Down
8 changes: 4 additions & 4 deletions src/Core/src/Layouts/FlexEnums.cs
Expand Up @@ -75,10 +75,12 @@ public struct FlexBasis
{
bool _isLength;
bool _isRelative;
public static FlexBasis Auto = new();
public float Length { get; }
internal bool IsAuto => !_isLength && !_isRelative;
internal bool IsRelative => _isRelative;

public static readonly FlexBasis Auto = new();

public FlexBasis(float length, bool isRelative = false)
{
if (length < 0)
Expand All @@ -91,8 +93,6 @@ public FlexBasis(float length, bool isRelative = false)
}

public static implicit operator FlexBasis(float length)
{
return new FlexBasis(length);
}
=> new FlexBasis(length);
}
}
5 changes: 4 additions & 1 deletion src/Core/src/Primitives/FlowDirection.cs
@@ -1,6 +1,9 @@
namespace Microsoft.Maui
using System.ComponentModel;

namespace Microsoft.Maui
{
/// <include file="../../docs/Microsoft.Maui/FlowDirection.xml" path="Type[@FullName='Microsoft.Maui.FlowDirection']/Docs" />
[TypeConverter(typeof(Converters.FlowDirectionTypeConverter))]
public enum FlowDirection
{
/// <include file="../../docs/Microsoft.Maui/FlowDirection.xml" path="//Member[@MemberName='MatchParent']/Docs" />
Expand Down