|
|
|
@ -198,6 +198,29 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions |
|
|
|
throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a grid length", node); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (type.Equals(types.ColumnDefinition) || type.Equals(types.RowDefinition)) |
|
|
|
{ |
|
|
|
try |
|
|
|
{ |
|
|
|
var gridLength = GridLength.Parse(text); |
|
|
|
|
|
|
|
result = new AvaloniaXamlIlGridLengthAstNode(node, types, gridLength); |
|
|
|
|
|
|
|
var definitionConstructorGridLength = type.GetConstructor(new List<IXamlType> {types.GridLength}); |
|
|
|
var lengthNode = new AvaloniaXamlIlGridLengthAstNode(node, types, gridLength); |
|
|
|
var definitionTypeRef = new XamlAstClrTypeReference(node, type, false); |
|
|
|
|
|
|
|
result = new XamlAstNewClrObjectNode(node, definitionTypeRef, |
|
|
|
definitionConstructorGridLength, new List<IXamlAstValueNode> {lengthNode}); |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
catch |
|
|
|
{ |
|
|
|
throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a grid length", node); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (type.Equals(types.Cursor)) |
|
|
|
{ |
|
|
|
@ -211,16 +234,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (type.Equals(types.ColumnDefinitions)) |
|
|
|
{ |
|
|
|
return ConvertDefinitionList(node, text, types, types.ColumnDefinitions, types.ColumnDefinition, "column definitions", out result); |
|
|
|
} |
|
|
|
|
|
|
|
if (type.Equals(types.RowDefinitions)) |
|
|
|
{ |
|
|
|
return ConvertDefinitionList(node, text, types, types.RowDefinitions, types.RowDefinition, "row definitions", out result); |
|
|
|
} |
|
|
|
|
|
|
|
if (types.IBrush.IsAssignableFrom(type)) |
|
|
|
{ |
|
|
|
if (Color.TryParse(text, out Color color)) |
|
|
|
@ -295,46 +308,69 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
result = null; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
private static bool ConvertDefinitionList( |
|
|
|
IXamlAstValueNode node, |
|
|
|
string text, |
|
|
|
AvaloniaXamlIlWellKnownTypes types, |
|
|
|
IXamlType listType, |
|
|
|
IXamlType elementType, |
|
|
|
string errorDisplayName, |
|
|
|
out IXamlAstValueNode result) |
|
|
|
{ |
|
|
|
try |
|
|
|
// Keep it in the end, so more specific parsers can be applied.
|
|
|
|
var itemType = GetElementType(type, context.Configuration.WellKnownTypes); |
|
|
|
if (itemType is not null |
|
|
|
&& types.AvaloniaList.MakeGenericType(itemType).IsAssignableFrom(type)) |
|
|
|
{ |
|
|
|
var lengths = GridLength.ParseLengths(text); |
|
|
|
|
|
|
|
var definitionTypeRef = new XamlAstClrTypeReference(node, elementType, false); |
|
|
|
|
|
|
|
var definitionConstructorGridLength = elementType.GetConstructor(new List<IXamlType> {types.GridLength}); |
|
|
|
const StringSplitOptions trimOption = (StringSplitOptions)2; // StringSplitOptions.TrimEntries
|
|
|
|
var separators = new[] { "," }; |
|
|
|
var splitOptions = StringSplitOptions.RemoveEmptyEntries | trimOption; |
|
|
|
|
|
|
|
IXamlAstValueNode CreateDefinitionNode(GridLength length) |
|
|
|
var attribute = type.CustomAttributes.FirstOrDefault(a => a.Type == types.AvaloniaListAttribute); |
|
|
|
if (attribute is not null) |
|
|
|
{ |
|
|
|
var lengthNode = new AvaloniaXamlIlGridLengthAstNode(node, types, length); |
|
|
|
|
|
|
|
return new XamlAstNewClrObjectNode(node, definitionTypeRef, |
|
|
|
definitionConstructorGridLength, new List<IXamlAstValueNode> {lengthNode}); |
|
|
|
if (attribute.Properties.TryGetValue("Separators", out var separatorsArray)) |
|
|
|
{ |
|
|
|
separators = ((Array)separatorsArray)?.OfType<string>().ToArray(); |
|
|
|
} |
|
|
|
if (attribute.Properties.TryGetValue("SplitOptions", out var splitOptionsObj)) |
|
|
|
{ |
|
|
|
splitOptions = (StringSplitOptions)splitOptionsObj; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
var items = text.Split(separators, splitOptions ^ trimOption); |
|
|
|
// Compiler targets netstandard, so we need to emulate StringSplitOptions.TrimEntries, if it was requested.
|
|
|
|
if (splitOptions.HasFlag(trimOption)) |
|
|
|
{ |
|
|
|
items = items.Select(i => i.Trim()).ToArray(); |
|
|
|
} |
|
|
|
|
|
|
|
var definitionNodes = |
|
|
|
new List<IXamlAstValueNode>(lengths.Select(CreateDefinitionNode)); |
|
|
|
if (itemType is null) |
|
|
|
{ |
|
|
|
throw new XamlX.XamlLoadException($"Type '{type.Name}' is not a collection type.", node); |
|
|
|
} |
|
|
|
|
|
|
|
result = new AvaloniaXamlIlAvaloniaListConstantAstNode(node, types, listType, elementType, definitionNodes); |
|
|
|
var nodes = new IXamlAstValueNode[items.Length]; |
|
|
|
for (var index = 0; index < items.Length; index++) |
|
|
|
{ |
|
|
|
var success = XamlTransformHelpers.TryGetCorrectlyTypedValue( |
|
|
|
context, |
|
|
|
new XamlAstTextNode(node, items[index], true, context.Configuration.WellKnownTypes.String), |
|
|
|
itemType, out var itemNode); |
|
|
|
if (!success) |
|
|
|
{ |
|
|
|
result = null; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
nodes[index] = itemNode; |
|
|
|
} |
|
|
|
|
|
|
|
result = new AvaloniaXamlIlAvaloniaListConstantAstNode(node, types, type, itemType, nodes); |
|
|
|
return true; |
|
|
|
} |
|
|
|
catch |
|
|
|
{ |
|
|
|
throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a {errorDisplayName}", node); |
|
|
|
} |
|
|
|
|
|
|
|
result = null; |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
private static IXamlType GetElementType(IXamlType type, XamlTypeWellKnownTypes types) |
|
|
|
{ |
|
|
|
return type.GetAllInterfaces().FirstOrDefault(i => |
|
|
|
i.FullName.StartsWith(types.IEnumerableT.FullName))? |
|
|
|
.GenericArguments[0]; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|