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);
            }
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
            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)
                                                                          ));
                    }
Beispiel #4
0
        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());
        }