Beispiel #1
0
        public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
        {
            if (!(node is XamlIlAstObjectNode on))
            {
                return(node);
            }
            var nonDirectiveChildren = on.Children.Where(a => !(a is XamlIlAstXmlDirective)).ToList();

            if (on.Arguments.Count != 0 ||
                nonDirectiveChildren.Count != 1 ||
                !(nonDirectiveChildren[0] is IXamlIlAstValueNode vn) ||
                !vn.Type.GetClrType().Equals(context.Configuration.WellKnownTypes.String))
            {
                return(node);
            }

            if (XamlIlTransformHelpers.TryGetCorrectlyTypedValue(context, vn, on.Type.GetClrType(), out var rv))
            {
                if (nonDirectiveChildren.Count != on.Children.Count)
                {
                    rv = new XamlIlValueWithManipulationNode(rv, rv,
                                                             new XamlIlManipulationGroupNode(rv, on.Children.OfType <XamlIlAstXmlDirective>()));
                }
                return(rv);
            }

            if (on.Type.GetClrType().IsValueType)
            {
                throw new XamlIlLoadException(
                          $"Unable to convert value {(vn as XamlIlAstTextNode)?.Text}) to {on.Type.GetClrType()}", vn);
            }

            // Parser not found, isn't a value type, probably a regular object creation node with text content
            return(node);
        }
Beispiel #2
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlAstNewClrObjectNode n))
            {
                return(null);
            }

            var type = n.Type.GetClrType();
            var ctor = n.Constructor ?? type.FindConstructor();

            if (ctor == null)
            {
                throw new XamlIlLoadException("Unable to find default constructor and no non-default one is specified",
                                              n);
            }

            for (var c = 0; c < n.Arguments.Count; c++)
            {
                context.Emit(n.Arguments[c], codeGen, ctor.Parameters[c]);
            }

            var gen = codeGen
                      .Emit(OpCodes.Newobj, ctor);


            return(XamlIlNodeEmitResult.Type(0, type));
        }
        private XamlIlNodeEmitResult EmitCore(IXamlIlAstNode value, IXamlIlCodeGen codeGen)
        {
            XamlIlNodeEmitResult res = null;

            foreach (var e in _emitters)
            {
                if (e is IXamlIlAstNodeEmitter ve)
                {
                    res = ve.Emit(value, this, codeGen);
                    if (res != null)
                    {
                        return(res);
                    }
                }
            }

            if (value is IXamlIlAstEmitableNode en)
            {
                return(en.Emit(this, codeGen));
            }
            else
            {
                throw new XamlIlLoadException("Unable to find emitter for node type: " + value.GetType().FullName,
                                              value);
            }
        }
        public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
        {
            if (node is XamlIlAstObjectNode ni && ni.Type is XamlIlAstXmlTypeReference type)
            {
                foreach (var d in context.Configuration.KnownDirectives)
                {
                    if (type.XmlNamespace == d.ns && type.Name == d.name)
                    {
                        var vnodes = new List <IXamlIlAstValueNode>();
                        foreach (var ch in ni.Children)
                        {
                            if (ch is IXamlIlAstValueNode vn)
                            {
                                vnodes.Add(vn);
                            }
                            if (context.StrictMode)
                            {
                                throw new XamlIlParseException(
                                          "Only value nodes are allowed as directive children elements", ch);
                            }
                        }

                        return(new XamlIlAstXmlDirective(ni, type.XmlNamespace, type.Name, vnodes));
                    }
                }
            }

            return(node);
        }
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlCodeGen codeGen)
        {
            if (!(node is XamlIlInstanceMethodCallBaseNode mc))
            {
                return(null);
            }
            for (var c = 0; c < mc.Arguments.Count; c++)
            {
                context.Emit(mc.Arguments[c], codeGen, mc.Method.Parameters[c]);
            }
            codeGen.Generator.Emit(mc.Method.IsStatic ? OpCodes.Call : OpCodes.Callvirt, mc.Method);

            var isVoid = mc.Method.ReturnType.Equals(context.Configuration.WellKnownTypes.Void);

            if (mc is XamlIlInstanceNoReturnMethodCallNode && !isVoid)
            {
                codeGen.Generator.Emit(OpCodes.Pop);
            }
            if (mc is XamlIlStaticReturnMethodCallNode && isVoid)
            {
                throw new XamlIlLoadException(
                          $"XamlIlStaticReturnMethodCallNode expects a value while {mc.Method.Name} returns void", node);
            }

            return(isVoid ? XamlIlNodeEmitResult.Void : XamlIlNodeEmitResult.Type(mc.Method.ReturnType));
        }
        public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
        {
            if (node is XamlIlAstObjectNode ni)
            {
                var t = ni.Type.GetClrType();
                if (t.IsValueType)
                {
                    throw new XamlIlLoadException(
                              "Value types can only be loaded via converters. We don't want to mess with ldloca.s, ldflda and other weird stuff",
                              node);
                }

                TransformContent(context, ni);
                var ctor = TransformArgumentsAndGetConstructor(context, ni);

                return(new XamlIlValueWithManipulationNode(ni,
                                                           new XamlIlAstNewClrObjectNode(ni, ni.Type.GetClrType(), ctor, ni.Arguments),
                                                           new XamlIlObjectInitializationNode(ni,
                                                                                              new XamlIlManipulationGroupNode(ni)
                {
                    Children = ni.Children.Cast <IXamlIlAstManipulationNode>().ToList()
                }, ni.Type.GetClrType())));
            }

            return(node);
        }
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode value, IXamlIlCodeGen codeGen, IXamlIlType expectedType)
        {
            var res          = EmitCore(value, codeGen);
            var returnedType = res.ReturnType;

            if (returnedType != null || expectedType != null)
            {
                if (returnedType != null && expectedType == null)
                {
                    throw new XamlIlLoadException(
                              $"Emit of node {value} resulted in {returnedType.GetFqn()} while caller expected void", value);
                }

                if (expectedType != null && returnedType == null)
                {
                    throw new XamlIlLoadException(
                              $"Emit of node {value} resulted in void while caller expected {expectedType.GetFqn()}", value);
                }

                if (!expectedType.IsAssignableFrom(returnedType))
                {
                    throw new XamlIlLoadException(
                              $"Emit of node {value} resulted in  {returnedType.GetFqn()} which is not convertible to expected {expectedType.GetFqn()}",
                              value);
                }

                if (returnedType.IsValueType && !expectedType.IsValueType)
                {
                    codeGen.Generator.Emit(OpCodes.Box, returnedType);
                }
            }

            return(res);
        }
Beispiel #8
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlCodeGen codeGen)
        {
            if (!(node is XamlIlAstNewClrObjectNode n))
            {
                return(null);
            }
            var type = n.Type.GetClrType();

            var argTypes = n.Arguments.Select(a => a.Type.GetClrType()).ToList();
            var ctor     = type.FindConstructor(argTypes);

            if (ctor == null)
            {
                throw new XamlIlLoadException(
                          $"Unable to find public constructor for type {type.GetFqn()}({string.Join(", ", argTypes.Select(at => at.GetFqn()))})",
                          n);
            }

            for (var c = 0; c < n.Arguments.Count; c++)
            {
                var ctorArg = n.Arguments[c];
                context.Emit(ctorArg, codeGen, ctor.Parameters[c]);
            }

            var gen = codeGen.Generator
                      .Emit(OpCodes.Newobj, ctor);


            return(XamlIlNodeEmitResult.Type(type));
        }
Beispiel #9
0
        private XamlIlNodeEmitResult EmitNode(IXamlIlAstNode value, IXamlIlEmitter codeGen)
        {
            if (File != null)
            {
                codeGen.InsertSequencePoint(File, value.Line, value.Position);
            }

            XamlIlNodeEmitResult res = null;

            foreach (var e in Emitters)
            {
                if (e is IXamlIlAstNodeEmitter ve)
                {
                    res = ve.Emit(value, this, codeGen);
                    if (res != null)
                    {
                        return(res);
                    }
                }
            }

            if (value is IXamlIlAstEmitableNode en)
            {
                return(en.Emit(this, codeGen));
            }
            else
            {
                throw new XamlIlLoadException("Unable to find emitter for node type: " + value.GetType().FullName,
                                              value);
            }
        }
 public IXamlIlAstNode Error(IXamlIlAstNode node, Exception e)
 {
     if (StrictMode)
     {
         throw e;
     }
     return(node);
 }
 public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
 {
     if (node is XamlIlManipulationGroupNode group && group.Children.Count == 1)
     {
         return(group.Children[0]);
     }
     return(node);
 }
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlObjectInitializationNode init))
            {
                return(null);
            }
            var supportInitType    = context.Configuration.TypeMappings.SupportInitialize;
            var supportsInitialize = supportInitType != null &&
                                     context.Configuration.TypeMappings.SupportInitialize
                                     .IsAssignableFrom(init.Type);

            if (supportsInitialize)
            {
                codeGen
                // We need a copy for/EndInit
                .Emit(OpCodes.Dup);
                if (!init.SkipBeginInit)
                {
                    codeGen
                    .Emit(OpCodes.Dup)
                    .EmitCall(supportInitType.FindMethod(m => m.Name == "BeginInit"));
                }
            }


            var addToParentStack = context.RuntimeContext.ParentListField != null &&
                                   !init.Type.IsValueType &&
                                   context.GetOrCreateItem <XamlIlNeedsParentStackCache>().NeedsParentStack(node);

            if (addToParentStack)
            {
                using (var local = context.GetLocal(init.Type))
                    codeGen
                    .Stloc(local.Local)
                    .Ldloc(context.ContextLocal)
                    .Ldloc(local.Local)
                    .EmitCall(context.RuntimeContext.PushParentMethod)
                    .Ldloc(local.Local);
            }

            context.Emit(init.Manipulation, codeGen, null);

            if (addToParentStack)
            {
                codeGen
                .Ldloc(context.ContextLocal)
                .EmitCall(context.RuntimeContext.PopParentMethod, true);
            }

            if (supportsInitialize)
            {
                codeGen
                .EmitCall(supportInitType.FindMethod(m => m.Name == "EndInit"));
            }


            return(XamlIlNodeEmitResult.Void(1));
        }
Beispiel #13
0
        public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
        {
            if (node is XamlIlPropertyAssignmentNode pa &&
                pa.Property.Name == "Name" &&
                pa.Property.DeclaringType.FullName == "Avalonia.StyledElement")
            {
                if (context.ParentNodes().FirstOrDefault() is XamlIlManipulationGroupNode mg &&
                    mg.Children.OfType <AvaloniaNameScopeRegistrationXamlIlNode>().Any())
                {
                    return(node);
                }

                IXamlIlAstValueNode value = null;
                for (var c = 0; c < pa.Values.Count; c++)
                {
                    if (pa.Values[c].Type.GetClrType().Equals(context.Configuration.WellKnownTypes.String))
                    {
                        value = pa.Values[c];
                        if (!(value is XamlIlAstTextNode))
                        {
                            var local = new XamlIlAstCompilerLocalNode(value);
                            // Wrap original in local initialization
                            pa.Values[c] = new XamlIlAstLocalInitializationNodeEmitter(value, value, local);
                            // Use local
                            value = local;
                        }

                        break;
                    }
                }

                if (value != null)
                {
                    return new XamlIlManipulationGroupNode(pa)
                           {
                               Children =
                               {
                                   pa,
                                   new AvaloniaNameScopeRegistrationXamlIlNode(value, context.GetAvaloniaTypes())
                               }
                           }
                }
                ;
            }

            if (!context.ParentNodes().Any() &&
                node is XamlIlValueWithManipulationNode mnode)
            {
                mnode.Manipulation = new XamlIlManipulationGroupNode(mnode,
                                                                     new[]
                {
                    mnode.Manipulation,
                    new HandleRootObjectScopeNode(mnode, context.GetAvaloniaTypes())
                });
            }
            return(node);
        }
 public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
 {
     if (node is XamlIlAstXmlTypeReference xmlref)
     {
         var type = ResolveType(context, xmlref.XmlNamespace, xmlref.Name, xmlref.GenericArguments, xmlref);
         return(new XamlIlAstClrTypeReference(xmlref, type));
     }
     return(node);
 }
        public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
        {
            if (node is AvaloniaXamlIlTargetTypeMetadataNode md)
            {
                return(md.Value);
            }

            return(node);
        }
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlPropertyAssignmentNode an))
                return null;
            var callOp = an.Property.Setter.IsStatic ? OpCodes.Call : OpCodes.Callvirt;
            context.Emit(an.Value, codeGen, an.Property.Setter.Parameters.Last());
            codeGen.Emit(callOp, an.Property.Setter);

            return XamlIlNodeEmitResult.Void(1);
        }
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter ilgen)
        {
            if (!(node is XamlIlMarkupExtensionNode me))
            {
                return(null);
            }
            XamlIlNeedsParentStackCache.Verify(context, node);

            var prop = context.ParentNodes().OfType <XamlIlPropertyAssignmentNode>().FirstOrDefault();

            var needProvideValueTarget = me.ProvideValue.Parameters.Count != 0 &&
                                         context.RuntimeContext.PropertyTargetObject != null &&
                                         prop != null;

            void EmitPropertyDescriptor()
            {
                if (context.Configuration.TypeMappings.ProvideValueTargetPropertyEmitter
                    ?.Invoke(context, ilgen, prop.Property) == true)
                {
                    return;
                }
                ilgen.Ldstr(prop.Property.Name);
            }

            context.Emit(me.Value, ilgen, me.Value.Type.GetClrType());

            if (me.ProvideValue.Parameters.Count > 0)
            {
                ilgen
                .Emit(OpCodes.Ldloc, context.ContextLocal);
            }

            if (needProvideValueTarget)
            {
                ilgen
                .Ldloc(context.ContextLocal);
                EmitPropertyDescriptor();
                ilgen
                .Stfld(context.RuntimeContext.PropertyTargetProperty);
            }

            ilgen.EmitCall(me.ProvideValue);

            if (needProvideValueTarget)
            {
                ilgen
                .Ldloc(context.ContextLocal)
                .Ldnull()
                .Stfld(context.RuntimeContext.PropertyTargetProperty);
            }



            return(XamlIlNodeEmitResult.Type(0, me.ProvideValue.ReturnType));
        }
Beispiel #18
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlPropertyValueManipulationNode pvm))
            {
                return(null);
            }
            codeGen.EmitCall(pvm.Property.Getter);
            context.Emit(pvm.Manipulation, codeGen, null);

            return(XamlIlNodeEmitResult.Void(1));
        }
        public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
        {
            if (node is XamlIlAstClrProperty prop && prop.Getter != null)
            {
                foreach (var adder in XamlIlTransformHelpers.FindPossibleAdders(context, prop.Getter.ReturnType))
                {
                    prop.Setters.Add(new AdderSetter(prop.Getter, adder));
                }
            }

            return(node);
        }
Beispiel #20
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlCodeGen codeGen)
        {
            if (!(node is XamlIlPropertyValueManipulationNode pvm))
            {
                return(null);
            }
            codeGen.Generator.Emit(pvm.Property.Getter.IsStatic ? OpCodes.Call : OpCodes.Callvirt,
                                   pvm.Property.Getter);
            context.Emit(pvm.Manipulation, codeGen, null);

            return(XamlIlNodeEmitResult.Void);
        }
Beispiel #21
0
        public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
        {
            if (node is XamlIlAstObjectNode ni)
            {
                XamlIlAstXamlPropertyValueNode propertyNode = null;

                for (var c = ni.Children.Count - 1; c >= 0; c--)
                {
                    var child = ni.Children[c];
                    if (child is IXamlIlAstValueNode valueNode)
                    {
                        if (propertyNode == null)
                        {
                            var contentProperty = context.Configuration.FindContentProperty(ni.Type.GetClrType());
                            if (contentProperty != null)
                            {
                                propertyNode = new XamlIlAstXamlPropertyValueNode(ni,
                                                                                  new XamlIlAstClrProperty(ni, contentProperty, context.Configuration),
                                                                                  Array.Empty <IXamlIlAstValueNode>());
                            }
                            else
                            {
                                var adders = XamlIlTransformHelpers.FindPossibleAdders(context, ni.Type.GetClrType());
                                if (adders.Count == 0)
                                {
                                    throw new XamlIlParseException(
                                              $"No Content property or any Add methods found for type {ni.Type.GetClrType().GetFqn()}",
                                              child);
                                }
                                propertyNode = new XamlIlAstXamlPropertyValueNode(ni, new XamlIlAstClrProperty(ni,
                                                                                                               "Content", ni.Type.GetClrType(), null,
                                                                                                               adders.Select(a => new XamlIlDirectCallPropertySetter(a)
                                {
                                    BinderParameters = { AllowMultiple = true }
                                })),
                                                                                  Array.Empty <IXamlIlAstValueNode>());
                            }
                        }
                        // We are going in reverse order, so insert at the beginning
                        propertyNode.Values.Insert(0, valueNode);
                        ni.Children.RemoveAt(c);
                    }
                }

                if (propertyNode != null)
                {
                    ni.Children.Add(propertyNode);
                }
            }

            return(node);
        }
Beispiel #22
0
        public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
        {
            // Our code base expects XAML parser to prefer `FooExtension` to `Foo` even with `<Foo>` syntax
            // This is the legacy of Portable.Xaml, so we emulate that behavior here

            if (node is XamlIlAstXmlTypeReference tref &&
                tref.Name == "Binding" &&
                tref.XmlNamespace == "https://github.com/avaloniaui")
            {
                tref.IsMarkupExtension = true;
            }
            return(node);
        }
Beispiel #23
0
 public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
 {
     if (!(node is XamlIlAstTextNode text))
     {
         return(null);
     }
     if (!text.Type.GetClrType().Equals(context.Configuration.WellKnownTypes.String))
     {
         throw new XamlIlLoadException("Text node type wasn't resolved to well-known System.String", node);
     }
     codeGen.Emit(OpCodes.Ldstr, text.Text);
     return(XamlIlNodeEmitResult.Type(0, text.Type.GetClrType()));
 }
        public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
        {
            if (node is XamlIlAstXmlTypeReference xmlref)
            {
                var type = ResolveType(context, xmlref, context.StrictMode);
                if (type == null)
                {
                    return(node);
                }
                return(new XamlIlAstClrTypeReference(node, type));
            }

            return(node);
        }
Beispiel #25
0
        public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
        {
            if (node is XamlIlAstXmlTypeReference xmlref)
            {
                var resolved = ResolveType(context, xmlref, context.StrictMode);
                if (resolved == null)
                {
                    return(node);
                }
                return(resolved);
            }

            return(node);
        }
Beispiel #26
0
 public IXamlIlAstNode Visit(IXamlIlAstNode node)
 {
     if (_cache.ContainsKey(node))
     {
         return(node);
     }
     if (node is IXamlIlAstNodeNeedsParentStack nps && nps.NeedsParentStack)
     {
         _cache[node] = true;
         foreach (var parent in _parents)
         {
             _cache[parent] = true;
         }
     }
 public IXamlIlAstNode Visit(IXamlIlAstNode node)
 {
     #if XAMLIL_DEBUG
     return(_transformer.Transform(_context, node));
     #else
     try
     {
         return(_transformer.Transform(_context, node));
     }
     catch (Exception e) when(!(e is XmlException))
     {
         throw new XamlIlParseException(
                   "Internal compiler error while transforming node " + node + ":\n" + e, node);
     }
     #endif
 }
Beispiel #28
0
        public XamlIlNodeEmitResult Emit(IXamlIlAstNode node, XamlIlEmitContext context, IXamlIlEmitter codeGen)
        {
            if (!(node is XamlIlValueWithManipulationNode vwm))
            {
                return(null);
            }
            var created = context.Emit(vwm.Value, codeGen, vwm.Type.GetClrType());

            if (vwm.Manipulation != null &&
                !(vwm.Manipulation is XamlIlManipulationGroupNode grp && grp.Children.Count == 0))
            {
                codeGen.Emit(OpCodes.Dup);
                context.Emit(vwm.Manipulation, codeGen, null);
            }
            return(XamlIlNodeEmitResult.Type(0, created.ReturnType));
        }
Beispiel #29
0
        public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
        {
            if (node is XamlIlAstClrProperty prop)
            {
                var n     = prop.Name + "Property";
                var field =
                    prop.DeclaringType.Fields
                    .FirstOrDefault(f => f.Name == n);
                if (field != null)
                {
                    return(new XamlIlAvaloniaProperty(prop, field, context.GetAvaloniaTypes()));
                }
            }

            return(node);
        }
        public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
        {
            if (node is XamlIlAstObjectNode ni)
            {
                SubTransform(context, ni);

                return(new XamlIlValueWithManipulationNode(ni,
                                                           new XamlIlAstNewClrObjectNode(ni, ni.Type, ni.Arguments),
                                                           new XamlIlManipulationGroupNode(ni)
                {
                    Children = ni.Children.Cast <IXamlIlAstManipulationNode>().ToList()
                }));
            }

            return(node);
        }