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 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 static XamlIlAstClrTypeReference ResolveType(XamlIlAstTransformationContext context, string xmlns, string name, bool isMarkupExtension, List <XamlIlAstXmlTypeReference> typeArguments, IXamlIlLineInfo lineInfo, bool strict) { if (typeArguments == null || typeArguments.Count == 0) { var cache = context.GetOrCreateItem <TypeResolverCache>(); var cacheKey = (xmlns, name, isMarkupExtension); if (cache.CacheDictionary.TryGetValue(cacheKey, out var type)) { if (type == null) { return(null); } return(new XamlIlAstClrTypeReference(lineInfo, type, isMarkupExtension)); } var res = ResolveTypeCore(context, xmlns, name, isMarkupExtension, typeArguments, lineInfo, strict); cache.CacheDictionary[cacheKey] = res?.Type; return(res); } else { return(ResolveTypeCore(context, xmlns, name, isMarkupExtension, typeArguments, lineInfo, strict)); } }
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 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 IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node) { if (node is XamlIlManipulationGroupNode group && group.Children.Count == 1) { return(group.Children[0]); } return(node); }
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 static AvaloniaXamlIlWellKnownTypes GetAvaloniaTypes(this XamlIlAstTransformationContext ctx) { if (ctx.TryGetItem <AvaloniaXamlIlWellKnownTypes>(out var rv)) { return(rv); } ctx.SetItem(rv = new AvaloniaXamlIlWellKnownTypes(ctx)); return(rv); }
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 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 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 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 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); }
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node) { if (node is IXamlIlAstValueNode vn) { if (context.ParentNodes().FirstOrDefault() is XamlIlMarkupExtensionNode) { return(node); } if (XamlIlTransformHelpers.TryConvertMarkupExtension(context, vn, out var rv)) { return(rv); } } return(node); }
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node) { if (node is XamlIlAstXamlPropertyValueNode pn) { var assignments = XamlIlTransformHelpers.GeneratePropertyAssignments(context, pn.Property.GetClrProperty(), pn.Values); return(new XamlIlManipulationGroupNode(pn) { Children = assignments }); } else { return(node); } }
void SubTransform(XamlIlAstTransformationContext context, XamlIlAstObjectNode ni) { var valueIndexes = new List <int>(); for (var c = 0; c < ni.Children.Count; c++) { if (ni.Children[c] is IXamlIlAstValueNode) { valueIndexes.Add(c); } } if (valueIndexes.Count == 0) { return; } var type = ni.Type.GetClrType(); IXamlIlAstValueNode VNode(int ind) => (IXamlIlAstValueNode)ni.Children[ind]; var contentProperty = context.Configuration.FindContentProperty(type); if (contentProperty == null) { foreach (var ind in valueIndexes) { if (XamlIlTransformHelpers.TryCallAdd(context, null, type, VNode(ind), out var addCall)) { ni.Children[ind] = addCall; } else { throw new XamlIlLoadException( $"Type `{type.GetFqn()} does not have content property and suitable Add({VNode(ind).Type.GetClrType().GetFqn()}) not found", VNode(ind)); } } } else { XamlIlTransformHelpers.GeneratePropertyAssignments(context, contentProperty, valueIndexes.Count, num => VNode(valueIndexes[num]), (i, v) => ni.Children[valueIndexes[i]] = v); } }
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node) { if (node is XamlIlAstObjectNode no) { foreach (var d in no.Children.OfType <XamlIlAstXmlDirective>().ToList()) { if (d.Namespace == XamlNamespaces.Xaml2006) { if (d.Name == "Precompile" || d.Name == "Class") { no.Children.Remove(d); } } } } return(node); }
public static IXamlIlAvaloniaPropertyNode CreateNode(XamlIlAstTransformationContext context, string propertyName, IXamlIlAstTypeReference selectorTypeReference, IXamlIlLineInfo lineInfo) { XamlIlAstNamePropertyReference forgedReference; var parser = new PropertyParser(); var parsedPropertyName = parser.Parse(new CharacterReader(propertyName.AsSpan())); if (parsedPropertyName.owner == null) { forgedReference = new XamlIlAstNamePropertyReference(lineInfo, selectorTypeReference, propertyName, selectorTypeReference); } else { var xmlOwner = parsedPropertyName.ns; if (xmlOwner != null) { xmlOwner += ":"; } xmlOwner += parsedPropertyName.owner; var tref = XamlIlTypeReferenceResolver.ResolveType(context, xmlOwner, false, lineInfo, true); var propertyFieldName = parsedPropertyName.name + "Property"; var found = tref.Type.GetAllFields() .FirstOrDefault(f => f.IsStatic && f.IsPublic && f.Name == propertyFieldName); if (found == null) { throw new XamlIlParseException( $"Unable to find {propertyFieldName} field on type {tref.Type.GetFullName()}", lineInfo); } return(new XamlIlAvaloniaPropertyFieldNode(context.GetAvaloniaTypes(), lineInfo, found)); } var clrProperty = ((XamlIlAstClrProperty) new XamlIlPropertyReferenceResolver().Transform(context, forgedReference)); return(new XamlIlAvaloniaPropertyNode(lineInfo, context.Configuration.TypeSystem.GetType("Avalonia.AvaloniaProperty"), clrProperty)); }
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node) { if (node is XamlIlAstObjectNode on) { foreach (var ch in on.Children) { if (ch is XamlIlAstXamlPropertyValueNode pn && pn.Property.GetClrProperty().Getter?.ReturnType.Equals(context.GetAvaloniaTypes().Transitions) == true) { for (var c = 0; c < pn.Values.Count; c++) { pn.Values[c] = new AvaloniaXamlIlTargetTypeMetadataNode(pn.Values[c], on.Type, AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Transitions); } } } } return(node); }
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node) { if (node is XamlIlAstObjectNode on && on.Arguments.Count == 0) { var ctors = on.Type.GetClrType().Constructors; if (!ctors.Any(c => c.IsPublic && !c.IsStatic && c.Parameters.Count == 0)) { var sp = context.Configuration.TypeMappings.ServiceProvider; if (ctors.Any(c => c.IsPublic && !c.IsStatic && c.Parameters.Count == 1 && c.Parameters[0] .Equals(sp))) { on.Arguments.Add(new InjectServiceProviderNode(sp, on)); } } } return(node); }
public AvaloniaXamlIlWellKnownTypes(XamlIlAstTransformationContext ctx) { XamlIlTypes = ctx.Configuration.WellKnownTypes; AvaloniaObject = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaObject"); IAvaloniaObject = ctx.Configuration.TypeSystem.GetType("Avalonia.IAvaloniaObject"); AvaloniaObjectExtensions = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaObjectExtensions"); AvaloniaProperty = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaProperty"); BindingPriority = ctx.Configuration.TypeSystem.GetType("Avalonia.Data.BindingPriority"); IBinding = ctx.Configuration.TypeSystem.GetType("Avalonia.Data.IBinding"); IDisposable = ctx.Configuration.TypeSystem.GetType("System.IDisposable"); Transitions = ctx.Configuration.TypeSystem.GetType("Avalonia.Animation.Transitions"); AssignBindingAttribute = ctx.Configuration.TypeSystem.GetType("Avalonia.Data.AssignBindingAttribute"); AvaloniaObjectBindMethod = AvaloniaObjectExtensions.FindMethod("Bind", IDisposable, false, IAvaloniaObject, AvaloniaProperty, IBinding, ctx.Configuration.WellKnownTypes.Object); UnsetValueType = ctx.Configuration.TypeSystem.GetType("Avalonia.UnsetValueType"); AvaloniaObjectSetValueMethod = AvaloniaObject.FindMethod("SetValue", XamlIlTypes.Void, false, AvaloniaProperty, XamlIlTypes.Object, BindingPriority); }
public static IXamlIlType ResolveType(XamlIlAstTransformationContext context, string xmlName, IXamlIlLineInfo lineInfo, bool strict) { var pair = xmlName.Split(new[] { ':' }, 2); var(shortNs, name) = pair.Length == 1 ? ("", pair[0]) : (pair[0], pair[1]); if (!context.NamespaceAliases.TryGetValue(shortNs, out var xmlns)) { if (strict) { throw new XamlIlParseException( $"Unable to resolve type namespace alias {shortNs}", lineInfo); } return(null); } return(ResolveType(context, xmlns, name, new List <XamlIlAstXmlTypeReference>(), lineInfo, strict)); }
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node) { if (node is XamlIlAstObjectNode ni) { var argDirectives = ni.Children.OfType <XamlIlAstXmlDirective>() .Where(d => d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Arguments").ToList(); if (argDirectives.Count > 1 && context.StrictMode) { throw new XamlIlParseException("x:Arguments directive is specified more than once", argDirectives[1]); } if (argDirectives.Count == 0) { return(node); } ni.Arguments = argDirectives[0].Values; ni.Children.Remove(argDirectives[0]); } return(node); }
/// <summary> /// Converts x:Name directives to regular Name assignments /// </summary> /// <returns></returns> public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node) { if (node is XamlIlAstObjectNode on) { for (var c = 0; c < on.Children.Count; c++) { var ch = on.Children[c]; if (ch is XamlIlAstXmlDirective d && d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Name") { on.Children[c] = new XamlIlAstXamlPropertyValueNode(d, new XamlIlAstNamePropertyReference(d, on.Type, "Name", on.Type), d.Values); } } } return(node); }
public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node) { if (!(node is XamlIlPropertyAssignmentNode pa)) { return(node); } var deferredAttrs = context.Configuration.TypeMappings.DeferredContentPropertyAttributes; if (deferredAttrs.Count == 0) { return(node); } if (!pa.Property.CustomAttributes.Any(ca => deferredAttrs.Any(da => da.Equals(ca.Type)))) { return(node); } pa.Value = new XamlIlDeferredContentNode(pa.Value, context.Configuration); return(node); }
public AvaloniaXamlIlWellKnownTypes(XamlIlAstTransformationContext ctx) { XamlIlTypes = ctx.Configuration.WellKnownTypes; XamlIlMappings = ctx.Configuration.TypeMappings; AvaloniaObject = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaObject"); IAvaloniaObject = ctx.Configuration.TypeSystem.GetType("Avalonia.IAvaloniaObject"); AvaloniaObjectExtensions = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaObjectExtensions"); AvaloniaProperty = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaProperty"); AvaloniaPropertyT = ctx.Configuration.TypeSystem.GetType("Avalonia.AvaloniaProperty`1"); BindingPriority = ctx.Configuration.TypeSystem.GetType("Avalonia.Data.BindingPriority"); IBinding = ctx.Configuration.TypeSystem.GetType("Avalonia.Data.IBinding"); IDisposable = ctx.Configuration.TypeSystem.GetType("System.IDisposable"); Transitions = ctx.Configuration.TypeSystem.GetType("Avalonia.Animation.Transitions"); AssignBindingAttribute = ctx.Configuration.TypeSystem.GetType("Avalonia.Data.AssignBindingAttribute"); AvaloniaObjectBindMethod = AvaloniaObjectExtensions.FindMethod("Bind", IDisposable, false, IAvaloniaObject, AvaloniaProperty, IBinding, ctx.Configuration.WellKnownTypes.Object); UnsetValueType = ctx.Configuration.TypeSystem.GetType("Avalonia.UnsetValueType"); StyledElement = ctx.Configuration.TypeSystem.GetType("Avalonia.StyledElement"); INameScope = ctx.Configuration.TypeSystem.GetType("Avalonia.Controls.INameScope"); INameScopeRegister = INameScope.GetMethod( new FindMethodMethodSignature("Register", XamlIlTypes.Void, XamlIlTypes.String, XamlIlTypes.Object) { IsStatic = false, DeclaringOnly = true, IsExactMatch = true }); INameScopeComplete = INameScope.GetMethod( new FindMethodMethodSignature("Complete", XamlIlTypes.Void) { IsStatic = false, DeclaringOnly = true, IsExactMatch = true }); NameScope = ctx.Configuration.TypeSystem.GetType("Avalonia.Controls.NameScope"); NameScopeSetNameScope = NameScope.GetMethod(new FindMethodMethodSignature("SetNameScope", XamlIlTypes.Void, StyledElement, INameScope) { IsStatic = true }); AvaloniaObjectSetValueMethod = AvaloniaObject.FindMethod("SetValue", XamlIlTypes.Void, false, AvaloniaProperty, XamlIlTypes.Object, BindingPriority); }