public static bool CustomValueConverter(XamlIlAstTransformationContext context, IXamlIlAstValueNode node, IXamlIlType type, out IXamlIlAstValueNode result) { if (type.FullName == "System.TimeSpan" && node is XamlIlAstTextNode tn && !tn.Text.Contains(":")) { var seconds = double.Parse(tn.Text, CultureInfo.InvariantCulture); result = new XamlIlStaticOrTargetedReturnMethodCallNode(tn, type.FindMethod("FromSeconds", type, false, context.Configuration.WellKnownTypes.Double), new[] { new XamlIlConstantNode(tn, context.Configuration.WellKnownTypes.Double, seconds) }); return(true); } if (type.FullName == "Avalonia.AvaloniaProperty") { var scope = context.ParentNodes().OfType <AvaloniaXamlIlTargetTypeMetadataNode>().FirstOrDefault(); if (scope == null) { throw new XamlIlLoadException("Unable to find the parent scope for AvaloniaProperty lookup", node); } if (!(node is XamlIlAstTextNode text)) { throw new XamlIlLoadException("Property should be a text node", node); } result = XamlIlAvaloniaPropertyHelper.CreateNode(context, text.Text, scope.TargetType, text); return(true); } result = null; return(false); }
public static bool CustomValueConverter(AstTransformationContext context, IXamlAstValueNode node, IXamlType type, out IXamlAstValueNode result) { if (!(node is XamlAstTextNode textNode)) { result = null; return(false); } var text = textNode.Text; var types = context.GetAvaloniaTypes(); if (AvaloniaXamlIlLanguageParseIntrinsics.TryConvert(context, node, text, type, types, out result)) { return(true); } if (type.FullName == "Avalonia.AvaloniaProperty") { var scope = context.ParentNodes().OfType <AvaloniaXamlIlTargetTypeMetadataNode>().FirstOrDefault(); if (scope == null) { throw new XamlX.XamlLoadException("Unable to find the parent scope for AvaloniaProperty lookup", node); } result = XamlIlAvaloniaPropertyHelper.CreateNode(context, text, scope.TargetType, node); return(true); } result = null; return(false); }
public XamlIlAvaloniaPropertyFieldNode(AvaloniaXamlIlWellKnownTypes types, IXamlLineInfo lineInfo, IXamlField field) : base(lineInfo) { _field = field; AvaloniaPropertyType = XamlIlAvaloniaPropertyHelper.GetAvaloniaPropertyType(field, types, lineInfo); }
public static bool CustomValueConverter(AstTransformationContext context, IXamlAstValueNode node, IXamlType type, out IXamlAstValueNode result) { if (!(node is XamlAstTextNode textNode)) { result = null; return(false); } var text = textNode.Text; var types = context.GetAvaloniaTypes(); if (type.FullName == "System.TimeSpan") { var tsText = text.Trim(); if (!TimeSpan.TryParse(tsText, CultureInfo.InvariantCulture, out var timeSpan)) { // // shorthand seconds format (ie. "0.25") if (!tsText.Contains(":") && double.TryParse(tsText, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var seconds)) { timeSpan = TimeSpan.FromSeconds(seconds); } else { throw new XamlX.XamlLoadException($"Unable to parse {text} as a time span", node); } } result = new XamlStaticOrTargetedReturnMethodCallNode(node, type.FindMethod("FromTicks", type, false, types.Long), new[] { new XamlConstantNode(node, types.Long, timeSpan.Ticks) }); return(true); } if (type.Equals(types.FontFamily)) { result = new AvaloniaXamlIlFontFamilyAstNode(types, text, node); return(true); } if (type.FullName == "Avalonia.AvaloniaProperty") { var scope = context.ParentNodes().OfType <AvaloniaXamlIlTargetTypeMetadataNode>().FirstOrDefault(); if (scope == null) { throw new XamlX.XamlLoadException("Unable to find the parent scope for AvaloniaProperty lookup", node); } result = XamlIlAvaloniaPropertyHelper.CreateNode(context, text, scope.TargetType, node); return(true); } result = null; return(false); }
public XamlIlNodeEmitResult Emit(XamlIlEmitContext context, IXamlIlEmitter codeGen) { if (!XamlIlAvaloniaPropertyHelper.Emit(context, codeGen, Property)) { throw new XamlIlLoadException(Property.Name + " is not an AvaloniaProperty", this); } return(XamlIlNodeEmitResult.Type(0, Type.GetClrType())); }
public static bool CustomValueConverter(AstTransformationContext context, IXamlAstValueNode node, IXamlType type, out IXamlAstValueNode result) { if (!(node is XamlAstTextNode textNode)) { result = null; return(false); } var text = textNode.Text; var types = context.GetAvaloniaTypes(); if (type.FullName == "System.TimeSpan") { var tsText = text.Trim(); if (!TimeSpan.TryParse(tsText, CultureInfo.InvariantCulture, out var timeSpan)) { // // shorthand seconds format (ie. "0.25") if (!tsText.Contains(":") && double.TryParse(tsText, NumberStyles.Float | NumberStyles.AllowThousands, CultureInfo.InvariantCulture, out var seconds)) { timeSpan = TimeSpan.FromSeconds(seconds); } else { throw new XamlX.XamlLoadException($"Unable to parse {text} as a time span", node); } } result = new XamlStaticOrTargetedReturnMethodCallNode(node, type.FindMethod("FromTicks", type, false, types.Long), new[] { new XamlConstantNode(node, types.Long, timeSpan.Ticks) }); return(true); } if (type.Equals(types.FontFamily)) { result = new AvaloniaXamlIlFontFamilyAstNode(types, text, node); return(true); } if (type.Equals(types.Thickness)) { var thickness = Thickness.Parse(text); result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Thickness, types.ThicknessFullConstructor, new[] { thickness.Left, thickness.Top, thickness.Right, thickness.Bottom }); return(true); } if (type.Equals(types.Point)) { var point = Point.Parse(text); result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Point, types.PointFullConstructor, new[] { point.X, point.Y }); return(true); } if (type.Equals(types.Vector)) { var vector = Vector.Parse(text); result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Vector, types.VectorFullConstructor, new[] { vector.X, vector.Y }); return(true); } if (type.Equals(types.Size)) { var size = Size.Parse(text); result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Size, types.SizeFullConstructor, new[] { size.Width, size.Height }); return(true); } if (type.Equals(types.Matrix)) { var matrix = Matrix.Parse(text); result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Matrix, types.MatrixFullConstructor, new[] { matrix.M11, matrix.M12, matrix.M21, matrix.M22, matrix.M31, matrix.M32 }); return(true); } if (type.Equals(types.CornerRadius)) { var cornerRadius = CornerRadius.Parse(text); result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.CornerRadius, types.CornerRadiusFullConstructor, new[] { cornerRadius.TopLeft, cornerRadius.TopRight, cornerRadius.BottomRight, cornerRadius.BottomLeft }); return(true); } if (type.FullName == "Avalonia.AvaloniaProperty") { var scope = context.ParentNodes().OfType <AvaloniaXamlIlTargetTypeMetadataNode>().FirstOrDefault(); if (scope == null) { throw new XamlX.XamlLoadException("Unable to find the parent scope for AvaloniaProperty lookup", node); } result = XamlIlAvaloniaPropertyHelper.CreateNode(context, text, scope.TargetType, node); return(true); } result = null; return(false); }
private static IXamlIlBindingPathNode TransformBindingPath(AstTransformationContext context, IXamlLineInfo lineInfo, IXamlType startType, IEnumerable <BindingExpressionGrammar.INode> bindingExpression) { List <IXamlIlBindingPathElementNode> transformNodes = new List <IXamlIlBindingPathElementNode>(); List <IXamlIlBindingPathElementNode> nodes = new List <IXamlIlBindingPathElementNode>(); foreach (var astNode in bindingExpression) { var targetType = nodes.Count == 0 ? startType : nodes[nodes.Count - 1].Type; switch (astNode) { case BindingExpressionGrammar.EmptyExpressionNode _: break; case BindingExpressionGrammar.NotNode _: transformNodes.Add(new XamlIlNotPathElementNode(context.Configuration.WellKnownTypes.Boolean)); break; case BindingExpressionGrammar.StreamNode _: IXamlType observableType; if (targetType.GenericTypeDefinition?.Equals(context.Configuration.TypeSystem.FindType("System.IObservable`1")) == true) { observableType = targetType; } else { observableType = targetType.GetAllInterfaces().FirstOrDefault(i => i.GenericTypeDefinition?.Equals(context.Configuration.TypeSystem.FindType("System.IObservable`1")) ?? false); } if (observableType != null) { nodes.Add(new XamlIlStreamObservablePathElementNode(observableType.GenericArguments[0])); break; } bool foundTask = false; for (var currentType = targetType; currentType != null; currentType = currentType.BaseType) { if (currentType.GenericTypeDefinition.Equals(context.Configuration.TypeSystem.GetType("System.Threading.Tasks.Task`1"))) { foundTask = true; nodes.Add(new XamlIlStreamTaskPathElementNode(currentType.GenericArguments[0])); break; } } if (foundTask) { break; } throw new XamlX.XamlParseException($"Compiled bindings do not support stream bindings for objects of type {targetType.FullName}.", lineInfo); case BindingExpressionGrammar.PropertyNameNode propName: var avaloniaPropertyFieldNameMaybe = propName.PropertyName + "Property"; var avaloniaPropertyFieldMaybe = targetType.GetAllFields().FirstOrDefault(f => f.IsStatic && f.IsPublic && f.Name == avaloniaPropertyFieldNameMaybe); if (avaloniaPropertyFieldMaybe != null) { nodes.Add(new XamlIlAvaloniaPropertyPropertyPathElementNode(avaloniaPropertyFieldMaybe, XamlIlAvaloniaPropertyHelper.GetAvaloniaPropertyType(avaloniaPropertyFieldMaybe, context.GetAvaloniaTypes(), lineInfo))); } else { var clrProperty = targetType.GetAllProperties().FirstOrDefault(p => p.Name == propName.PropertyName); if (clrProperty is null) { throw new XamlX.XamlParseException($"Unable to resolve property of name '{propName.PropertyName}' on type '{targetType}'.", lineInfo); } nodes.Add(new XamlIlClrPropertyPathElementNode(clrProperty)); } break; case BindingExpressionGrammar.IndexerNode indexer: { if (targetType.IsArray) { nodes.Add(new XamlIlArrayIndexerPathElementNode(targetType, indexer.Arguments, lineInfo)); break; } IXamlProperty property = null; for (var currentType = targetType; currentType != null; currentType = currentType.BaseType) { var defaultMemberAttribute = currentType.CustomAttributes.FirstOrDefault(x => x.Type.Namespace == "System.Reflection" && x.Type.Name == "DefaultMemberAttribute"); if (defaultMemberAttribute != null) { property = targetType.GetAllProperties().FirstOrDefault(x => x.Name == (string)defaultMemberAttribute.Parameters[0]); break; } } ; if (property is null) { throw new XamlX.XamlParseException($"The type '${targetType}' does not have an indexer.", lineInfo); } IEnumerable <IXamlType> parameters = property.IndexerParameters; List <IXamlAstValueNode> values = new List <IXamlAstValueNode>(); int currentParamIndex = 0; foreach (var param in parameters) { var textNode = new XamlAstTextNode(lineInfo, indexer.Arguments[currentParamIndex], type: context.Configuration.WellKnownTypes.String); if (!XamlTransformHelpers.TryGetCorrectlyTypedValue(context, textNode, param, out var converted)) { throw new XamlX.XamlParseException( $"Unable to convert indexer parameter value of '{indexer.Arguments[currentParamIndex]}' to {param.GetFqn()}", textNode); } values.Add(converted); currentParamIndex++; } bool isNotifyingCollection = targetType.GetAllInterfaces().Any(i => i.FullName == "System.Collections.Specialized.INotifyCollectionChanged"); nodes.Add(new XamlIlClrIndexerPathElementNode(property, values, string.Join(",", indexer.Arguments), isNotifyingCollection)); break; } case BindingExpressionGrammar.AttachedPropertyNameNode attachedProp: var avaloniaPropertyFieldName = attachedProp.PropertyName + "Property"; var avaloniaPropertyField = GetType(attachedProp.Namespace, attachedProp.TypeName).GetAllFields().FirstOrDefault(f => f.IsStatic && f.IsPublic && f.Name == avaloniaPropertyFieldName); nodes.Add(new XamlIlAvaloniaPropertyPropertyPathElementNode(avaloniaPropertyField, XamlIlAvaloniaPropertyHelper.GetAvaloniaPropertyType(avaloniaPropertyField, context.GetAvaloniaTypes(), lineInfo))); break; case BindingExpressionGrammar.SelfNode _: nodes.Add(new SelfPathElementNode(targetType)); break; case VisualAncestorBindingExpressionNode visualAncestor: nodes.Add(new FindVisualAncestorPathElementNode(visualAncestor.Type, visualAncestor.Level)); break; case TemplatedParentBindingExpressionNode templatedParent: var templatedParentField = context.GetAvaloniaTypes().StyledElement.GetAllFields() .FirstOrDefault(f => f.IsStatic && f.IsPublic && f.Name == "TemplatedParentProperty"); nodes.Add(new XamlIlAvaloniaPropertyPropertyPathElementNode( templatedParentField, templatedParent.Type)); break; case BindingExpressionGrammar.AncestorNode ancestor: if (ancestor.Namespace is null && ancestor.TypeName is null) { var styledElementType = context.GetAvaloniaTypes().StyledElement; var ancestorType = context .ParentNodes() .OfType <XamlAstConstructableObjectNode>() .Where(x => styledElementType.IsAssignableFrom(x.Type.GetClrType())) .ElementAtOrDefault(ancestor.Level) ?.Type.GetClrType(); if (ancestorType is null) { throw new XamlX.XamlParseException("Unable to resolve implicit ancestor type based on XAML tree.", lineInfo); } nodes.Add(new FindAncestorPathElementNode(ancestorType, ancestor.Level)); } else { nodes.Add(new FindAncestorPathElementNode(GetType(ancestor.Namespace, ancestor.TypeName), ancestor.Level)); } break;