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); } }
IXamlIlConstructor TransformArgumentsAndGetConstructor(XamlIlAstTransformationContext context, XamlIlAstObjectNode n) { var type = n.Type.GetClrType(); var argTypes = n.Arguments.Select(a => a.Type.GetClrType()).ToList(); var ctor = type.FindConstructor(argTypes); if (ctor == null) { if (argTypes.Count != 0) { ctor = type.Constructors.FirstOrDefault(x => !x.IsStatic && x.IsPublic && x.Parameters.Count == argTypes.Count); } 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++) { if (!XamlIlTransformHelpers.TryGetCorrectlyTypedValue(context, n.Arguments[c], ctor.Parameters[c], out var arg)) { throw new XamlIlLoadException( $"Unable to convert {n.Arguments[c].Type.GetClrType().GetFqn()} to {ctor.Parameters[c].GetFqn()} for constructor of {n.Type.GetClrType().GetFqn()}", n.Arguments[c]); } n.Arguments[c] = arg; } return(ctor); }
XamlIlAstObjectNode ParseNewInstance(XElement el, bool root) { if (el.Name.LocalName.Contains(".")) { throw ParseError(el, "Dots aren't allowed in type names"); } var type = GetTypeReference(el); var i = new XamlIlAstObjectNode(el.AsLi(), type); foreach (var attr in el.Attributes()) { if (attr.Name.NamespaceName == "http://www.w3.org/2000/xmlns/" || (attr.Name.NamespaceName == "" && attr.Name.LocalName == "xmlns")) { if (!root) { throw ParseError(attr, "xmlns declarations are only allowed on the root element to preserve memory"); } } else if (attr.Name.NamespaceName.StartsWith("http://www.w3.org")) { // Silently ignore all xml-parser related attributes } // Parse type arguments else if (attr.Name.NamespaceName == XamlNamespaces.Xaml2006 && attr.Name.LocalName == "TypeArguments") { type.GenericArguments = ParseTypeArguments(attr.Value, el, attr.AsLi()); } // Parse as a directive else if (attr.Name.NamespaceName != "" && !attr.Name.LocalName.Contains(".")) { i.Children.Add(new XamlIlAstXmlDirective(el.AsLi(), attr.Name.NamespaceName, attr.Name.LocalName, new[] { ParseTextValueOrMarkupExtension(attr.Value, el, attr.AsLi()) } )); } // Parse as a property else { var pname = attr.Name.LocalName; var ptype = i.Type; if (pname.Contains(".")) { var parts = pname.Split(new[] { '.' }, 2); pname = parts[1]; var ns = attr.Name.Namespace == "" ? el.GetDefaultNamespace().NamespaceName : attr.Name.NamespaceName; ptype = new XamlIlAstXmlTypeReference(el.AsLi(), ns, parts[0]); } i.Children.Add(new XamlIlAstXamlPropertyValueNode(el.AsLi(), new XamlIlAstNamePropertyReference(el.AsLi(), ptype, pname, type), ParseTextValueOrMarkupExtension(attr.Value, el, attr.AsLi()))); } } foreach (var node in el.Nodes()) { if (node is XElement elementNode && elementNode.Name.LocalName.Contains(".")) { if (elementNode.HasAttributes) { throw ParseError(node, "Attributes aren't allowed on element properties"); } var pair = elementNode.Name.LocalName.Split(new[] { '.' }, 2); i.Children.Add(new XamlIlAstXamlPropertyValueNode(el.AsLi(), new XamlIlAstNamePropertyReference ( el.AsLi(), new XamlIlAstXmlTypeReference(el.AsLi(), elementNode.Name.NamespaceName, pair[0]), pair[1], type ), ParseValueNodeChildren(elementNode) )); }
public static IXamlIlAstValueNode Parse(IXamlIlLineInfo li, string ext, Func <string, XamlIlAstXmlTypeReference> typeResolver) { var ctx = new MeScannerContext(typeResolver, li); var scanner = new MeScanner(ctx, ext, li.Line, li.Position); var currentTypeStack = new Stack <MeScannerTypeName>(); IXamlIlAstValueNode ReadExtension() { if (scanner.Token != MeTokenType.Open) { throw new MeScannerParseException("Unexpected token " + scanner.Token); } scanner.Read(); if (scanner.Token != MeTokenType.TypeName) { throw new MeScannerParseException("Unexpected token " + scanner.Token); } var extType = scanner.TokenType; extType.TypeReference.IsMarkupExtension = true; currentTypeStack.Push(ctx.CurrentType); ctx.CurrentType = extType; var rv = new XamlIlAstObjectNode(li, extType.TypeReference); while (true) { scanner.Read(); if (scanner.Token == MeTokenType.Close) { break; } else if (scanner.Token == MeTokenType.PropertyName) { var prop = scanner.TokenProperty; scanner.Read(); if (scanner.Token != MeTokenType.EqualSign) { throw new MeScannerParseException("Unexpected token " + scanner.Token); } var propValue = Read(); rv.Children.Add(new XamlIlAstXamlPropertyValueNode(li, prop, propValue)); } else if (scanner.Token == MeTokenType.String || scanner.Token == MeTokenType.QuotedMarkupExtension || scanner.Token == MeTokenType.Open) { if (rv.Children.Count != 0) { throw new MeScannerParseException("Unexpected token after property list " + scanner.Token); } rv.Arguments.Add(ReadCurrent()); } else if (scanner.Token == MeTokenType.Comma) { continue; } else { throw new MeScannerParseException("Unexpected token " + scanner.Token); } } ctx.CurrentType = currentTypeStack.Pop(); return(rv); } IXamlIlAstValueNode Read() { scanner.Read(); return(ReadCurrent()); } IXamlIlAstValueNode ReadCurrent() { if (scanner.Token == MeTokenType.String) { return(new XamlIlAstTextNode(li, scanner.TokenText)); } if (scanner.Token == MeTokenType.Open) { return(ReadExtension()); } if (scanner.Token == MeTokenType.QuotedMarkupExtension) { return(Parse(li, scanner.TokenText, typeResolver)); } throw new MeScannerParseException("Unexpected token " + scanner.Token); } return(Read()); }