public bool EmitCall(IXamlPropertySetter setter, IXamlILEmitter emitter)
        {
            if (setter is XamlDirectEventSetter xdirect)
            {
                var paramType          = setter.Parameters[0];
                var expectedParameters = new [] { xdirect.WinUITypes.IXamlDirectObject, xdirect.WinUITypes.XamlPropertyIndex, paramType };

                IXamlType xamlDirectType = xdirect.WinUITypes.XamlDirect;
                var       setterMethod   = xamlDirectType.GetMethod(
                    new FindMethodMethodSignature("AddEventHandler",
                                                  emitter.TypeSystem.GetType("System.Void"),
                                                  xdirect.WinUITypes.IXamlDirectObject,
                                                  xdirect.WinUITypes.XamlEventIndex,
                                                  emitter.TypeSystem.GetType("System.Object")));

                using (var objLocal = emitter.LocalsPool.GetLocal(xdirect.WinUITypes.IXamlDirectObject))
                    using (var valLocal = emitter.LocalsPool.GetLocal(paramType))
                    {
                        emitter
                        .Stloc(valLocal.Local)
                        .Stloc(objLocal.Local)
                        .EmitCall(xamlDirectType.GetMethod(new FindMethodMethodSignature("GetDefault", xamlDirectType)
                        {
                            IsStatic = true
                        }))
                        .Ldloc(objLocal.Local)
                        .Ldc_I4((int)xdirect.EventIndex.GetLiteralValue())
                        .Ldloc(valLocal.Local)
                        .EmitCall(setterMethod);
                    }
                return(true);
            }
            return(false);
        }
        public XamlILNodeEmitResult Emit(IXamlAstNode node, XamlEmitContext <IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
        {
            if (node is XamlObjectFromDirectObjectNode objNode)
            {
                IXamlType xamlDirectType = context.GetWinUITypes().XamlDirect;
                codeGen
                .EmitCall(xamlDirectType.GetMethod(new FindMethodMethodSignature("GetDefault", xamlDirectType)
                {
                    IsStatic = true
                }));

                context.Emit(objNode.Value, codeGen, context.GetWinUITypes().IXamlDirectObject);
                codeGen
                .EmitCall(xamlDirectType.GetMethod(new FindMethodMethodSignature("GetObject", context.Configuration.WellKnownTypes.Object, context.GetWinUITypes().IXamlDirectObject)))
                .Castclass(objNode.Type.GetClrType());
                return(XamlILNodeEmitResult.Type(0, objNode.Type.GetClrType()));
            }
            else if (node is XamlDirectObjectFromObjectNode directObjNode)
            {
                IXamlType xamlDirectType = context.GetWinUITypes().XamlDirect;
                codeGen
                .EmitCall(xamlDirectType.GetMethod(new FindMethodMethodSignature("GetDefault", xamlDirectType)
                {
                    IsStatic = true
                }));

                context.Emit(directObjNode.Value, codeGen, context.Configuration.WellKnownTypes.Object);
                codeGen
                .EmitCall(xamlDirectType.GetMethod(new FindMethodMethodSignature("GetXamlDirectObject", context.GetWinUITypes().IXamlDirectObject, context.Configuration.WellKnownTypes.Object)));
                return(XamlILNodeEmitResult.Type(0, context.GetWinUITypes().IXamlDirectObject));
            }
            return(null);
        }
        public bool EmitCall(IXamlPropertySetter setter, IXamlILEmitter emitter)
        {
            if (setter is XamlDirectAdderSetter xdirect)
            {
                var paramType = setter.Parameters[0];

                IXamlType xamlDirectType      = xdirect.WinUITypes.XamlDirect;
                var       getCollectionMethod = xamlDirectType.GetMethod(
                    new FindMethodMethodSignature("GetXamlDirectObjectProperty",
                                                  xdirect.WinUITypes.IXamlDirectObject,
                                                  xdirect.WinUITypes.IXamlDirectObject,
                                                  xdirect.WinUITypes.XamlPropertyIndex));
                var addToCollection = xamlDirectType.GetMethod(
                    new FindMethodMethodSignature("AddToCollection",
                                                  emitter.TypeSystem.GetType("System.Void"),
                                                  xdirect.WinUITypes.IXamlDirectObject,
                                                  xdirect.WinUITypes.IXamlDirectObject));

                using (var objLocal = emitter.LocalsPool.GetLocal(xdirect.WinUITypes.IXamlDirectObject))
                    using (var valLocal = emitter.LocalsPool.GetLocal(paramType))
                    {
                        emitter
                        .Stloc(valLocal.Local)
                        .Stloc(objLocal.Local)
                        .EmitCall(xamlDirectType.GetMethod(new FindMethodMethodSignature("GetDefault", xamlDirectType)
                        {
                            IsStatic = true
                        }))
                        .Dup();

                        emitter
                        .Ldloc(objLocal.Local)
                        .Ldc_I4((int)xdirect.PropertyIndex.GetLiteralValue())
                        .EmitCall(getCollectionMethod);

                        if (paramType != xdirect.WinUITypes.IXamlDirectObject)
                        {
                            emitter
                            .EmitCall(xamlDirectType.GetMethod(new FindMethodMethodSignature("GetDefault", xamlDirectType)
                            {
                                IsStatic = true
                            }))
                            .Ldloc(valLocal.Local)
                            .EmitCall(xamlDirectType.FindMethod(m => m.Name == "GetXamlDirectObject"));
                        }
                        else
                        {
                            emitter.Ldloc(valLocal.Local);
                        }

                        emitter
                        .EmitCall(addToCollection);
                    }
                return(true);
            }
            return(false);
        }
Esempio n. 4
0
        public AvaloniaXamlIlAvaloniaListConstantAstNode(IXamlLineInfo lineInfo, AvaloniaXamlIlWellKnownTypes types, IXamlType listType, IXamlType elementType, IReadOnlyList <IXamlAstValueNode> values) : base(lineInfo)
        {
            _constructor           = listType.GetConstructor();
            _listAddMethod         = listType.GetMethod(new FindMethodMethodSignature("Add", types.XamlIlTypes.Void, elementType));
            _listSetCapacityMethod = listType.GetMethod(new FindMethodMethodSignature("set_Capacity", types.XamlIlTypes.Void, types.Int));

            _elementType = elementType;
            _values      = values;

            Type = new XamlAstClrTypeReference(lineInfo, listType, false);
        }
        public bool EmitCall(IXamlPropertySetter setter, IXamlILEmitter emitter)
        {
            if (setter is XamlDirectSetter xdirect)
            {
                var paramType          = setter.Parameters[0];
                var expectedParameters = new [] { xdirect.WinUITypes.IXamlDirectObject, xdirect.WinUITypes.XamlPropertyIndex, paramType };

                IXamlType xamlDirectType = xdirect.WinUITypes.XamlDirect;
                var       setterMethod   = xamlDirectType
                                           .FindMethod(m => !m.IsStatic &&
                                                       m.Name.StartsWith("Set") &&
                                                       m.ReturnType == emitter.TypeSystem.FindType("System.Void") &&
                                                       m.Parameters.SequenceEqual(expectedParameters));

                using (var objLocal = emitter.LocalsPool.GetLocal(xdirect.WinUITypes.IXamlDirectObject))
                    using (var valLocal = emitter.LocalsPool.GetLocal(paramType))
                    {
                        emitter
                        .Stloc(valLocal.Local)
                        .Stloc(objLocal.Local)
                        .EmitCall(xamlDirectType.GetMethod(new FindMethodMethodSignature("GetDefault", xamlDirectType)
                        {
                            IsStatic = true
                        }))
                        .Ldloc(objLocal.Local)
                        .Ldc_I4((int)xdirect.PropertyIndex.GetLiteralValue())
                        .Ldloc(valLocal.Local)
                        .EmitCall(setterMethod);
                    }
                return(true);
            }
            return(false);
        }
 public XamlILNodeEmitResult Emit(IXamlAstNode node, XamlEmitContext <IXamlILEmitter, XamlILNodeEmitResult> context, IXamlILEmitter codeGen)
 {
     if (node is XamlDirectNewObjectNode objNode)
     {
         IXamlType xamlDirectType = context.GetWinUITypes().XamlDirect;
         codeGen
         .EmitCall(xamlDirectType.GetMethod(new FindMethodMethodSignature("GetDefault", xamlDirectType)
         {
             IsStatic = true
         }))
         .Ldc_I4((int)objNode.TypeIndex.GetLiteralValue())
         .EmitCall(xamlDirectType.GetMethod(new FindMethodMethodSignature("CreateInstance", context.GetWinUITypes().IXamlDirectObject, context.GetWinUITypes().XamlTypeIndex)));
         return(XamlILNodeEmitResult.Type(0, context.GetWinUITypes().IXamlDirectObject));
     }
     return(null);
 }
        private void EmitLoadPropertyAccessorFactory(XamlIlEmitContext context, IXamlILEmitter codeGen, IXamlType type, string accessorFactoryName, bool isStatic = true)
        {
            var types             = context.GetAvaloniaTypes();
            var weakReferenceType = context.Configuration.TypeSystem.GetType("System.WeakReference`1").MakeGenericType(context.Configuration.WellKnownTypes.Object);
            FindMethodMethodSignature accessorFactorySignature = new FindMethodMethodSignature(accessorFactoryName, types.IPropertyAccessor, weakReferenceType, types.IPropertyInfo)
            {
                IsStatic = isStatic
            };

            codeGen.Ldftn(type.GetMethod(accessorFactorySignature));
        }
        public static bool TryConvert(AstTransformationContext context, IXamlAstValueNode node, string text, IXamlType type, AvaloniaXamlIlWellKnownTypes types, out IXamlAstValueNode result)
        {
            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))
            {
                try
                {
                    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);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a thickness", node);
                }
            }

            if (type.Equals(types.Point))
            {
                try
                {
                    var point = Point.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Point, types.PointFullConstructor,
                                                                         new[] { point.X, point.Y });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a point", node);
                }
            }

            if (type.Equals(types.Vector))
            {
                try
                {
                    var vector = Vector.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Vector, types.VectorFullConstructor,
                                                                         new[] { vector.X, vector.Y });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a vector", node);
                }
            }

            if (type.Equals(types.Size))
            {
                try
                {
                    var size = Size.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Size, types.SizeFullConstructor,
                                                                         new[] { size.Width, size.Height });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a size", node);
                }
            }

            if (type.Equals(types.Matrix))
            {
                try
                {
                    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);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a matrix", node);
                }
            }

            if (type.Equals(types.CornerRadius))
            {
                try
                {
                    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);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a corner radius", node);
                }
            }

            if (type.Equals(types.Color))
            {
                if (!Color.TryParse(text, out Color color))
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a color", node);
                }

                result = new XamlStaticOrTargetedReturnMethodCallNode(node,
                                                                      type.GetMethod(
                                                                          new FindMethodMethodSignature("FromUInt32", type, types.UInt)
                {
                    IsStatic = true
                }),
                                                                      new[] { new XamlConstantNode(node, types.UInt, color.ToUint32()) });

                return(true);
            }

            if (type.Equals(types.GridLength))
            {
                try
                {
                    var gridLength = GridLength.Parse(text);

                    result = new AvaloniaXamlIlGridLengthAstNode(node, types, gridLength);

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a grid length", node);
                }
            }

            if (type.Equals(types.Cursor))
            {
                if (TypeSystemHelpers.TryGetEnumValueNode(types.StandardCursorType, text, node, out var enumConstantNode))
                {
                    var cursorTypeRef = new XamlAstClrTypeReference(node, types.Cursor, false);

                    result = new XamlAstNewClrObjectNode(node, cursorTypeRef, types.CursorTypeConstructor, new List <IXamlAstValueNode> {
                        enumConstantNode
                    });

                    return(true);
                }
            }

            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 (type.Equals(types.Classes))
            {
                var classes    = text.Split(' ');
                var classNodes = classes.Select(c => new XamlAstTextNode(node, c, types.XamlIlTypes.String)).ToArray();

                result = new AvaloniaXamlIlAvaloniaListConstantAstNode(node, types, types.Classes, types.XamlIlTypes.String, classNodes);
                return(true);
            }

            result = null;
            return(false);
        }
Esempio n. 9
0
        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))
            {
                try
                {
                    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);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a thickness", node);
                }
            }

            if (type.Equals(types.Point))
            {
                try
                {
                    var point = Point.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Point, types.PointFullConstructor,
                                                                         new[] { point.X, point.Y });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a point", node);
                }
            }

            if (type.Equals(types.Vector))
            {
                try
                {
                    var vector = Vector.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Vector, types.VectorFullConstructor,
                                                                         new[] { vector.X, vector.Y });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a vector", node);
                }
            }

            if (type.Equals(types.Size))
            {
                try
                {
                    var size = Size.Parse(text);

                    result = new AvaloniaXamlIlVectorLikeConstantAstNode(node, types, types.Size, types.SizeFullConstructor,
                                                                         new[] { size.Width, size.Height });

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a size", node);
                }
            }

            if (type.Equals(types.Matrix))
            {
                try
                {
                    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);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a matrix", node);
                }
            }

            if (type.Equals(types.CornerRadius))
            {
                try
                {
                    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);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a corner radius", node);
                }
            }

            if (type.Equals(types.Color))
            {
                if (!Color.TryParse(text, out Color color))
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a color", node);
                }

                result = new XamlStaticOrTargetedReturnMethodCallNode(node,
                                                                      type.GetMethod(
                                                                          new FindMethodMethodSignature("FromUInt32", type, types.UInt)
                {
                    IsStatic = true
                }),
                                                                      new[] { new XamlConstantNode(node, types.UInt, color.ToUint32()) });

                return(true);
            }

            if (type.Equals(types.GridLength))
            {
                try
                {
                    var gridLength = GridLength.Parse(text);

                    result = new AvaloniaXamlIlGridLengthAstNode(node, types, gridLength);

                    return(true);
                }
                catch
                {
                    throw new XamlX.XamlLoadException($"Unable to parse \"{text}\" as a grid length", node);
                }
            }

            if (type.Equals(types.Cursor))
            {
                if (TypeSystemHelpers.TryGetEnumValueNode(types.StandardCursorType, text, node, out var enumConstantNode))
                {
                    var cursorTypeRef = new XamlAstClrTypeReference(node, types.Cursor, false);

                    result = new XamlAstNewClrObjectNode(node, cursorTypeRef, types.CursorTypeConstructor, new List <IXamlAstValueNode> {
                        enumConstantNode
                    });

                    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);
        }