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