public static bool TryConvertMarkupExtension(XamlIlAstTransformationContext context, IXamlIlAstValueNode node, out XamlIlMarkupExtensionNode o) { o = null; var nodeType = node.Type.GetClrType(); var candidates = GetMarkupExtensionProvideValueAlternatives(context, nodeType).ToList(); var so = context.Configuration.WellKnownTypes.Object; var sp = context.Configuration.TypeMappings.ServiceProvider; // Try non-object variant first and variants without IServiceProvider argument first var provideValue = candidates.FirstOrDefault(m => m.Parameters.Count == 0 && !m.ReturnType.Equals(so)) ?? candidates.FirstOrDefault(m => m.Parameters.Count == 0) ?? candidates.FirstOrDefault(m => m.Parameters.Count == 1 && m.Parameters[0].Equals(sp) && !m.ReturnType.Equals(so)) ?? candidates.FirstOrDefault(m => m.Parameters.Count == 1 && m.Parameters[0].Equals(sp)); if (provideValue == null) { if (node.Type.IsMarkupExtension) { throw new XamlIlParseException( $"{node.Type.GetClrType().GetFqn()} was resolved as markup extension, but doesn't have a matching ProvideValue/ProvideTypedValue method", node.Type); } return(false); } o = new XamlIlMarkupExtensionNode(node, provideValue, node); return(true); }
public XamlIlValueWithManipulationNode(IXamlIlLineInfo lineInfo, IXamlIlAstValueNode value, IXamlIlAstManipulationNode manipulation) : base(lineInfo, value) { Value = value; Manipulation = manipulation; }
public XamlIlLoadMethodDelegateNode(IXamlIlLineInfo lineInfo, IXamlIlAstValueNode value, IXamlIlType delegateType, IXamlIlMethod method) : base(lineInfo, value) { DelegateType = delegateType; Method = method; Type = new XamlIlAstClrTypeReference(value, DelegateType); }
public XamlIlPropertyAssignmentNode(IXamlIlLineInfo lineInfo, IXamlIlProperty property, IXamlIlAstValueNode value) : base(lineInfo) { Property = property; Value = value; }
public static bool TryConvertMarkupExtension(XamlIlAstTransformationContext context, IXamlIlAstValueNode node, IXamlIlProperty prop, out XamlIlMarkupExtensionNode o) { o = null; var nodeType = node.Type.GetClrType(); var candidates = nodeType.Methods.Where(m => m.Name == "ProvideValue" && m.IsPublic && !m.IsStatic) .ToList(); var so = context.Configuration.WellKnownTypes.Object; var sp = context.Configuration.TypeMappings.ServiceProvider; // Try non-object variant first and variants without IServiceProvider argument first var provideValue = candidates.FirstOrDefault(m => m.Parameters.Count == 0 && !m.ReturnType.Equals(so)) ?? candidates.FirstOrDefault(m => m.Parameters.Count == 0) ?? candidates.FirstOrDefault(m => m.Parameters.Count == 1 && m.Parameters[0].Equals(sp) && !m.ReturnType.Equals(so)) ?? candidates.FirstOrDefault(m => m.Parameters.Count == 1 && m.Parameters[0].Equals(sp)); if (provideValue == null) { return(false); } o = new XamlIlMarkupExtensionNode(node, prop, provideValue, node, null); return(true); }
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 XamlIlAstLocalInitializationNodeEmitter(IXamlIlLineInfo lineInfo, IXamlIlAstValueNode value, XamlIlAstCompilerLocalNode local) : base(lineInfo, value) { Value = value; Local = local; }
static IXamlIlAstValueNode FindAndRemoveKey(IXamlIlAstValueNode value) { IXamlIlAstValueNode keyNode = null; bool IsKeyDirective(object node) => node is XamlIlAstXmlDirective d && d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Key"; void ProcessDirective(object d) { var directive = (XamlIlAstXmlDirective)d; if (directive.Values.Count != 1) { throw new XamlIlParseException("Invalid number of arguments for x:Key directive", directive); } keyNode = directive.Values[0]; } void ProcessDirectiveCandidateList(IList nodes) { var d = nodes.OfType <object>().FirstOrDefault(IsKeyDirective); if (d != null) { ProcessDirective(d); nodes.Remove(d); } } IXamlIlAstManipulationNode VisitManipulationNode(IXamlIlAstManipulationNode man) { if (IsKeyDirective(man)) { ProcessDirective(man); return(new XamlIlManipulationGroupNode(man)); } if (man is XamlIlManipulationGroupNode grp) { ProcessDirectiveCandidateList(grp.Children); } if (man is XamlIlObjectInitializationNode init) { init.Manipulation = VisitManipulationNode(init.Manipulation); } return(man); } if (value is XamlIlAstObjectNode astObject) { ProcessDirectiveCandidateList(astObject.Children); } else if (value is XamlIlValueWithManipulationNode vman) { vman.Manipulation = VisitManipulationNode(vman.Manipulation); } return(keyNode); }
public XamlIlMarkupExtensionNode(IXamlIlLineInfo lineInfo, IXamlIlMethod provideValue, IXamlIlAstValueNode value) : base(lineInfo) { ProvideValue = provideValue; Value = value; Type = new XamlIlAstClrTypeReference(this, ProvideValue.ReturnType, false); }
public XamlIlPropertyEqualsSelector(XamlIlSelectorNode previous, IXamlIlProperty property, IXamlIlAstValueNode value) : base(previous) { Property = property; Value = value; }
public XamlIlMarkupExtensionNode(IXamlIlLineInfo lineInfo, IXamlIlProperty property, IXamlIlMethod provideValue, IXamlIlAstValueNode value, IXamlIlWrappedMethod manipulation) : base(lineInfo) { Property = property; ProvideValue = provideValue; Value = value; Manipulation = manipulation; }
public XamlIlAstXamlPropertyValueNode(IXamlIlLineInfo lineInfo, IXamlIlAstPropertyReference property, IXamlIlAstValueNode value) : base(lineInfo) { Property = property; Values = new List <IXamlIlAstValueNode> { value }; }
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 XamlIlDeferredContentNode(IXamlIlAstValueNode value, XamlIlTransformerConfiguration config) : base(value) { Value = value; var funcType = config.TypeSystem.GetType("System.Func`2") .MakeGenericType(config.TypeMappings.ServiceProvider, config.WellKnownTypes.Object); Type = new XamlIlAstClrTypeReference(value, funcType); }
public static bool TryGetCorrectlyTypedValue(XamlIlAstTransformationContext context, IXamlIlAstValueNode node, IXamlIlType type, out IXamlIlAstValueNode rv) { if (type.IsAssignableFrom(node.Type.GetClrType())) { rv = node; return(true); } return(TryConvertValue(context, node, type, null, out rv)); }
void CompileBuild(IXamlIlAstValueNode rootInstance, Func <string, IXamlIlType, IXamlIlTypeBuilder> createSubType, IXamlIlEmitter codeGen, XamlIlContext context, IXamlIlMethod compiledPopulate) { var needContextLocal = !(rootInstance is XamlIlAstNewClrObjectNode newObj && newObj.Arguments.Count == 0); var emitContext = InitCodeGen(createSubType, codeGen, context, needContextLocal); var rv = codeGen.DefineLocal(rootInstance.Type.GetClrType()); emitContext.Emit(rootInstance, codeGen, rootInstance.Type.GetClrType()); codeGen .Emit(OpCodes.Stloc, rv) .Emit(OpCodes.Ldarg_0) .Emit(OpCodes.Ldloc, rv) .Emit(OpCodes.Call, compiledPopulate) .Emit(OpCodes.Ldloc, rv) .Emit(OpCodes.Ret); }
public static bool TryCallAdd(XamlIlAstTransformationContext context, IXamlIlProperty targetProperty, IXamlIlType targetPropertyType, IXamlIlAstValueNode value, out IXamlIlAstManipulationNode rv) { var so = context.Configuration.WellKnownTypes.Object; rv = null; IXamlIlWrappedMethod FindAdderImpl(IXamlIlType targetType, IXamlIlType valueType, IXamlIlType keyType = null) { var candidates = targetType.FindMethods(m => !m.IsStatic && m.IsPublic && (m.Name == "Add" || m.Name.EndsWith(".Add"))).ToList(); bool CheckArg(IXamlIlType argType, bool allowObj) { if (allowObj && argType.Equals(so)) { return(true); } if (!allowObj && !argType.Equals(so) && argType.IsAssignableFrom(valueType)) { return(true); } return(false); } foreach (var allowObj in new[] { false, true }) { foreach (var m in candidates) { if (keyType == null && m.Parameters.Count == 1 && CheckArg(m.Parameters[0], allowObj)) { return(new XamlIlWrappedMethod(m)); } if (keyType != null && m.Parameters.Count == 2 && m.Parameters[0].IsAssignableFrom(keyType) && CheckArg(m.Parameters[1], allowObj)) { return(new XamlIlWrappedMethod(m)); } } } return(null); } IXamlIlWrappedMethod FindAdderWithCast(IXamlIlType originalType, IXamlIlType newTargetType, IXamlIlType valueType) { var m = FindAdderImpl(newTargetType, valueType); if (m == null) { return(null); } return(new XamlIlWrappedMethodWithCasts(m, new[] { originalType, m.ParametersWithThis[1] })); } IXamlIlWrappedMethod FindAdder(IXamlIlType valueType, IXamlIlType keyType = null) { if (keyType == null) { if (targetPropertyType.Equals(context.Configuration.WellKnownTypes.IEnumerable)) { return(FindAdderWithCast(targetPropertyType, context.Configuration.WellKnownTypes.IList, valueType)); } if (targetPropertyType.GenericTypeDefinition?.Equals(context.Configuration.WellKnownTypes .IEnumerableT) == true) { return(FindAdderWithCast( targetPropertyType, context.Configuration.WellKnownTypes.IListOfT .MakeGenericType(targetPropertyType.GenericArguments[0]), valueType)); } } return(FindAdderImpl(targetPropertyType, valueType, keyType)); } if (TryConvertMarkupExtension(context, value, targetProperty, out var ext)) { var adder = FindAdder(ext.ProvideValue.ReturnType); if (adder != null) { ext.Manipulation = adder; rv = ext; return(true); } } else { var vtype = value.Type.GetClrType(); IXamlIlAstValueNode keyNode = null; bool IsKeyDirective(object node) => node is XamlIlAstXmlDirective d && d.Namespace == XamlNamespaces.Xaml2006 && d.Name == "Key"; void ProcessDirective(object d) { var directive = (XamlIlAstXmlDirective)d; if (directive.Values.Count != 1) { throw new XamlIlParseException("Invalid number of arguments for x:Key directive", directive); } keyNode = directive.Values[0]; } void ProcessDirectiveCandidateList(IList nodes) { var d = nodes.OfType <object>().FirstOrDefault(IsKeyDirective); if (d != null) { ProcessDirective(d); nodes.Remove(d); } } IXamlIlAstManipulationNode VisitManipulationNode(IXamlIlAstManipulationNode man) { if (IsKeyDirective(man)) { ProcessDirective(man); return(new XamlIlManipulationGroupNode(man)); } if (man is XamlIlManipulationGroupNode grp) { ProcessDirectiveCandidateList(grp.Children); } if (man is XamlIlObjectInitializationNode init) { init.Manipulation = VisitManipulationNode(init.Manipulation); } return(man); } if (value is XamlIlAstObjectNode astObject) { ProcessDirectiveCandidateList(astObject.Children); } else if (value is XamlIlValueWithManipulationNode vman) { vman.Manipulation = VisitManipulationNode(vman.Manipulation); } var adder = FindAdder(vtype, keyNode?.Type.GetClrType()); if (adder != null) { var args = new List <IXamlIlAstValueNode>(); if (keyNode != null) { args.Add(keyNode); } args.Add(value); rv = new XamlIlNoReturnMethodCallNode(value, adder, args); if (targetProperty != null) { rv = new XamlIlPropertyValueManipulationNode(value, targetProperty, rv); } return(true); } } return(false); }
public XamlIlAstCompilerLocalNode(IXamlIlAstValueNode value) : this(value, value.Type.GetClrTypeReference()) { }
public XamlIlAstNeedsParentStackValueNode(IXamlIlLineInfo lineInfo, IXamlIlAstValueNode value) : base(lineInfo, value) { }
public XamlIlAstImperativeValueManipulation(IXamlIlLineInfo lineInfo, IXamlIlAstValueNode value, IXamlIlAstManipulationNode manipulation) : base(lineInfo) { Value = value; Manipulation = manipulation; }
public XamlIlAstRuntimeCastNode(IXamlIlLineInfo lineInfo, IXamlIlAstValueNode value, IXamlIlAstTypeReference castTo) : base(lineInfo) { Value = value; Type = castTo; }
public static bool TryCallAdd(XamlIlAstTransformationContext context, IXamlIlProperty targetProperty, IXamlIlType targetPropertyType, IXamlIlAstValueNode value, out IXamlIlAstManipulationNode rv) { if (TryConvertMarkupExtension(context, value, targetProperty, out var ext)) { var adder = new[] { ext.ProvideValue.ReturnType, context.Configuration.WellKnownTypes.Object } .Select(argType => targetPropertyType.FindMethod(m => !m.IsStatic && m.IsPublic && (m.Name == "Add" || m.Name.EndsWith(".Add")) && m.Parameters.Count == 1 && m.Parameters[0].Equals(argType))) .FirstOrDefault(m => m != null); if (adder != null) { ext.Manipulation = adder; rv = ext; return(true); } } if (context.Configuration.TryCallAdd(targetPropertyType, value, out var nret)) { if (targetProperty != null) { rv = new XamlIlPropertyValueManipulationNode(value, targetProperty, nret); } else { rv = nret; } return(true); } rv = null; return(false); }
public ScopeRegistrationNode(IXamlIlAstValueNode value) : base(value) { Value = value; }
protected XamlIlValueWithSideEffectNodeBase(IXamlIlLineInfo lineInfo, IXamlIlAstValueNode value) : base(lineInfo) { Value = value; }
public XamlIlValueNodeWithBeginInit(IXamlIlAstValueNode value) : base(value, value) { }
public override void VisitChildren(Visitor visitor) { Value = (IXamlIlAstValueNode)Value.Visit(visitor); }
public override void VisitChildren(IXamlIlAstVisitor visitor) => Name = (IXamlIlAstValueNode)Name.Visit(visitor);
public AvaloniaNameScopeRegistrationXamlIlNode(IXamlIlAstValueNode name, AvaloniaXamlIlWellKnownTypes types) : base(name) { _types = types; Name = name; }
public XamlIlToArrayNode(IXamlIlLineInfo lineInfo, IXamlIlAstTypeReference arrayType, IXamlIlAstValueNode value) : base(lineInfo) { Type = arrayType; Value = value; }
public static bool TryConvertValue(XamlIlAstTransformationContext context, IXamlIlAstValueNode node, IXamlIlType type, XamlIlAstClrProperty propertyContext, out IXamlIlAstValueNode rv) { rv = null; var cfg = context.Configuration; // Since we are doing a conversion anyway, it makes sense to check for the underlying nullable type if (type.GenericTypeDefinition?.Equals(cfg.WellKnownTypes.NullableT) == true) { type = type.GenericArguments[0]; } if (cfg.CustomValueConverter?.Invoke(context, node, type, out rv) == true) { return(true); } var nodeType = node.Type.GetClrType(); // Implicit type converters if (!nodeType.Equals(cfg.WellKnownTypes.String)) { return(false); } if (node is XamlIlAstTextNode tn) { if (type.IsEnum) { if (TypeSystemHelpers.TryGetEnumValueNode(type, tn.Text, tn, out var enumConstantNode)) { rv = enumConstantNode; return(true); } } // Well known types if (TypeSystemHelpers.ParseConstantIfTypeAllows(tn.Text, type, tn, out var constantNode)) { rv = constantNode; return(true); } if (type.FullName == "System.Type") { var resolvedType = XamlIlTypeReferenceResolver.ResolveType(context, tn.Text, false, tn, true); rv = new XamlIlTypeExtensionNode(tn, resolvedType, type); return(true); } if (cfg.WellKnownTypes.Delegate.IsAssignableFrom(type)) { var invoke = type.FindMethod(m => m.Name == "Invoke"); var rootType = context.RootObject.Type.GetClrType(); var handler = rootType.FindMethod(tn.Text, invoke.ReturnType, false, invoke.Parameters.ToArray()); if (handler != null) { rv = new XamlIlLoadMethodDelegateNode(tn, context.RootObject, type, handler); return(true); } } } IXamlIlAstValueNode CreateInvariantCulture() => new XamlIlStaticOrTargetedReturnMethodCallNode(node, cfg.WellKnownTypes.CultureInfo.Methods.First(x => x.IsPublic && x.IsStatic && x.Name == "get_InvariantCulture"), null); var candidates = type.Methods.Where(m => m.Name == "Parse" && m.ReturnType.Equals(type) && m.Parameters.Count > 0 && m.Parameters[0].Equals(cfg.WellKnownTypes.String)).ToList(); // Types with parse method var parser = candidates.FirstOrDefault(m => m.Parameters.Count == 2 && ( m.Parameters[1].Equals(cfg.WellKnownTypes.CultureInfo) || m.Parameters[1].Equals(cfg.WellKnownTypes.IFormatProvider) ) ) ?? candidates.FirstOrDefault(m => m.Parameters.Count == 1); if (parser != null) { var args = new List <IXamlIlAstValueNode> { node }; if (parser.Parameters.Count == 2) { args.Add(CreateInvariantCulture()); } rv = new XamlIlStaticOrTargetedReturnMethodCallNode(node, parser, args); return(true); } if (cfg.TypeMappings.TypeDescriptorContext != null) { IXamlIlType converterType = null; if (propertyContext?.TypeConverters.TryGetValue(type, out converterType) != true) { var typeConverterAttribute = cfg.GetCustomAttribute(type, cfg.TypeMappings.TypeConverterAttributes).FirstOrDefault(); if (typeConverterAttribute != null) { converterType = TryGetTypeConverterFromCustomAttribute(cfg, typeConverterAttribute); } } if (converterType != null) { var converterMethod = converterType.FindMethod("ConvertFrom", cfg.WellKnownTypes.Object, false, cfg.TypeMappings.TypeDescriptorContext, cfg.WellKnownTypes.CultureInfo, cfg.WellKnownTypes.Object); rv = new XamlIlAstNeedsParentStackValueNode(node, new XamlIlAstRuntimeCastNode(node, new XamlIlStaticOrTargetedReturnMethodCallNode(node, converterMethod, new[] { new XamlIlAstNewClrObjectNode(node, new XamlIlAstClrTypeReference(node, converterType, false), null, new List <IXamlIlAstValueNode>()), new XamlIlAstContextLocalNode(node, cfg.TypeMappings.TypeDescriptorContext), CreateInvariantCulture(), node }), new XamlIlAstClrTypeReference(node, type, false))); return(true); } } return(false); }