public void Is_Descendent_Not_OfType_Class()
        {
            var result = SelectorGrammar.Parse(":is(Control) :not(Button.foo)");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.IsSyntax {
                    TypeName = "Control"
                },
                new SelectorGrammar.DescendantSyntax {
                },
                new SelectorGrammar.NotSyntax
                {
                    Argument = new SelectorGrammar.ISyntax[]
                    {
                        new SelectorGrammar.OfTypeSyntax {
                            TypeName = "Button"
                        },
                        new SelectorGrammar.ClassSyntax {
                            Class = "foo"
                        },
                    },
                }
            },
                result);
        }
        public void Name()
        {
            var result = SelectorGrammar.Parse("#foo");

            Assert.Equal(
                new[] { new SelectorGrammar.NameSyntax {
                            Name = "foo"
                        }, },
                result);
        }
        public void Is()
        {
            var result = SelectorGrammar.Parse(":is(Button)");

            Assert.Equal(
                new[] { new SelectorGrammar.IsSyntax {
                            TypeName = "Button", Xmlns = ""
                        } },
                result);
        }
        public void Pseudoclass()
        {
            var result = SelectorGrammar.Parse(":foo");

            Assert.Equal(
                new[] { new SelectorGrammar.ClassSyntax {
                            Class = ":foo"
                        } },
                result);
        }
        public void NamespacedOfType()
        {
            var result = SelectorGrammar.Parse("x|Button");

            Assert.Equal(
                new[] { new SelectorGrammar.OfTypeSyntax {
                            TypeName = "Button", Xmlns = "x"
                        } },
                result);
        }
        public void Nesting_Class()
        {
            var result = SelectorGrammar.Parse("^.foo");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.NestingSyntax(),
                new SelectorGrammar.ClassSyntax {
                    Class = "foo"
                },
            },
                result);
        }
        public void Not_Nesting()
        {
            var result = SelectorGrammar.Parse(":not(^)");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.NotSyntax
                {
                    Argument = new[] { new SelectorGrammar.NestingSyntax() },
                }
            },
                result);
        }
        public void Nesting_Property()
        {
            var result = SelectorGrammar.Parse("^[Foo=bar]");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.NestingSyntax(),
                new SelectorGrammar.PropertySyntax {
                    Property = "Foo", Value = "bar"
                },
            },
                result);
        }
        public void NthLastChild_Variations(string input, int step, int offset)
        {
            var result = SelectorGrammar.Parse(input);

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.NthLastChildSyntax()
                {
                    Step   = step,
                    Offset = offset
                }
            },
                result);
        }
示例#10
0
        public void NamespacedIs_Name()
        {
            var result = SelectorGrammar.Parse(":is(x|Button)#foo");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.IsSyntax {
                    TypeName = "Button", Xmlns = "x"
                },
                new SelectorGrammar.NameSyntax {
                    Name = "foo"
                },
            },
                result);
        }
示例#11
0
        public void OfType_Class()
        {
            var result = SelectorGrammar.Parse("Button.foo");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.OfTypeSyntax {
                    TypeName = "Button"
                },
                new SelectorGrammar.ClassSyntax {
                    Class = "foo"
                },
            },
                result);
        }
        public void Nesting_NthChild()
        {
            var result = SelectorGrammar.Parse("^:nth-child(2n+1)");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.NestingSyntax(),
                new SelectorGrammar.NthChildSyntax()
                {
                    Step   = 2,
                    Offset = 1
                }
            },
                result);
        }
        public void OfType_Template_Nesting()
        {
            var result = SelectorGrammar.Parse("Button /template/ ^");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.OfTypeSyntax {
                    TypeName = "Button"
                },
                new SelectorGrammar.TemplateSyntax {
                },
                new SelectorGrammar.NestingSyntax(),
            },
                result);
        }
示例#14
0
        public void OfType_Property()
        {
            var result = SelectorGrammar.Parse("Button[Foo=bar]");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.OfTypeSyntax {
                    TypeName = "Button"
                },
                new SelectorGrammar.PropertySyntax {
                    Property = "Foo", Value = "bar"
                },
            },
                result);
        }
示例#15
0
        public void OfType_Name()
        {
            var result = SelectorGrammar.Parse("Button#foo");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.OfTypeSyntax {
                    TypeName = "Button"
                },
                new SelectorGrammar.NameSyntax {
                    Name = "foo"
                },
            },
                result);
        }
示例#16
0
        public void OfType_NthChild_Without_Offset()
        {
            var result = SelectorGrammar.Parse("Button:nth-child(2147483647n)");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.OfTypeSyntax {
                    TypeName = "Button"
                },
                new SelectorGrammar.NthChildSyntax()
                {
                    Step   = int.MaxValue,
                    Offset = 0
                }
            },
                result);
        }
示例#17
0
        public void OfType_NthLastChild()
        {
            var result = SelectorGrammar.Parse("Button:nth-last-child(2n+1)");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.OfTypeSyntax {
                    TypeName = "Button"
                },
                new SelectorGrammar.NthLastChildSyntax()
                {
                    Step   = 2,
                    Offset = 1
                }
            },
                result);
        }
示例#18
0
        public void OfType_NthChild_Even()
        {
            var result = SelectorGrammar.Parse("Button:nth-child(even)");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.OfTypeSyntax {
                    TypeName = "Button"
                },
                new SelectorGrammar.NthChildSyntax()
                {
                    Step   = 2,
                    Offset = 0
                }
            },
                result);
        }
示例#19
0
        public void Not_OfType()
        {
            var result = SelectorGrammar.Parse(":not(Button)");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.NotSyntax
                {
                    Argument = new SelectorGrammar.ISyntax[]
                    {
                        new SelectorGrammar.OfTypeSyntax {
                            TypeName = "Button"
                        },
                    },
                }
            },
                result);
        }
        public void OfType_AttachedProperty_WithNamespace()
        {
            var result = SelectorGrammar.Parse("Button[(x|Grid.Column)=1]");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.OfTypeSyntax {
                    TypeName = "Button"
                },
                new SelectorGrammar.AttachedPropertySyntax {
                    Xmlns    = "x",
                    TypeName = "Grid",
                    Property = "Column",
                    Value    = "1"
                },
            },
                result);
        }
示例#21
0
        public void OfType_Comma_Is_Class()
        {
            var result = SelectorGrammar.Parse("TextBlock, :is(Button).foo");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.OfTypeSyntax {
                    TypeName = "TextBlock"
                },
                new SelectorGrammar.CommaSyntax(),
                new SelectorGrammar.IsSyntax {
                    TypeName = "Button"
                },
                new SelectorGrammar.ClassSyntax {
                    Class = "foo"
                },
            },
                result);
        }
示例#22
0
        public void OfType_Not_Class()
        {
            var result = SelectorGrammar.Parse("Button:not(.foo)");

            Assert.Equal(
                new SelectorGrammar.ISyntax[]
            {
                new SelectorGrammar.OfTypeSyntax {
                    TypeName = "Button"
                },
                new SelectorGrammar.NotSyntax
                {
                    Argument = new SelectorGrammar.ISyntax[]
                    {
                        new SelectorGrammar.ClassSyntax {
                            Class = "foo"
                        },
                    },
                }
            },
                result);
        }
        public IXamlIlAstNode Transform(XamlIlAstTransformationContext context, IXamlIlAstNode node)
        {
            if (!(node is XamlIlAstObjectNode on && on.Type.GetClrType().FullName == "Avalonia.Styling.Style"))
            {
                return(node);
            }

            var pn = on.Children.OfType <XamlIlAstXamlPropertyValueNode>()
                     .FirstOrDefault(p => p.Property.GetClrProperty().Name == "Selector");

            if (pn == null)
            {
                return(node);
            }

            if (pn.Values.Count != 1)
            {
                throw new XamlIlParseException("Selector property should should have exactly one value", node);
            }

            if (pn.Values[0] is XamlIlSelectorNode)
            {
                //Deja vu. I've just been in this place before
                return(node);
            }

            if (!(pn.Values[0] is XamlIlAstTextNode tn))
            {
                throw new XamlIlParseException("Selector property should be a text node", node);
            }

            var selectorType = pn.Property.GetClrProperty().Getter.ReturnType;
            var initialNode  = new XamlIlSelectorInitialNode(node, selectorType);

            XamlIlSelectorNode Create(IEnumerable <SelectorGrammar.ISyntax> syntax,
                                      Func <string, string, XamlIlAstClrTypeReference> typeResolver)
            {
                XamlIlSelectorNode   result  = initialNode;
                XamlIlOrSelectorNode results = null;

                foreach (var i in syntax)
                {
                    switch (i)
                    {
                    case SelectorGrammar.OfTypeSyntax ofType:
                        result = new XamlIlTypeSelector(result, typeResolver(ofType.Xmlns, ofType.TypeName).Type, true);
                        break;

                    case SelectorGrammar.IsSyntax @is:
                        result = new XamlIlTypeSelector(result, typeResolver(@is.Xmlns, @is.TypeName).Type, false);
                        break;

                    case SelectorGrammar.ClassSyntax @class:
                        result = new XamlIlStringSelector(result, XamlIlStringSelector.SelectorType.Class, @class.Class);
                        break;

                    case SelectorGrammar.NameSyntax name:
                        result = new XamlIlStringSelector(result, XamlIlStringSelector.SelectorType.Name, name.Name);
                        break;

                    case SelectorGrammar.PropertySyntax property:
                    {
                        var type = result?.TargetType;

                        if (type == null)
                        {
                            throw new XamlIlParseException("Property selectors must be applied to a type.", node);
                        }

                        var targetProperty =
                            type.GetAllProperties().FirstOrDefault(p => p.Name == property.Property);

                        if (targetProperty == null)
                        {
                            throw new XamlIlParseException($"Cannot find '{property.Property}' on '{type}", node);
                        }

                        if (!XamlIlTransformHelpers.TryGetCorrectlyTypedValue(context,
                                                                              new XamlIlAstTextNode(node, property.Value, context.Configuration.WellKnownTypes.String),
                                                                              targetProperty.PropertyType, out var typedValue))
                        {
                            throw new XamlIlParseException(
                                      $"Cannot convert '{property.Value}' to '{targetProperty.PropertyType.GetFqn()}",
                                      node);
                        }

                        result = new XamlIlPropertyEqualsSelector(result, targetProperty, typedValue);
                        break;
                    }

                    case SelectorGrammar.ChildSyntax child:
                        result = new XamlIlCombinatorSelector(result, XamlIlCombinatorSelector.SelectorType.Child);
                        break;

                    case SelectorGrammar.DescendantSyntax descendant:
                        result = new XamlIlCombinatorSelector(result, XamlIlCombinatorSelector.SelectorType.Descendant);
                        break;

                    case SelectorGrammar.TemplateSyntax template:
                        result = new XamlIlCombinatorSelector(result, XamlIlCombinatorSelector.SelectorType.Template);
                        break;

                    case SelectorGrammar.NotSyntax not:
                        result = new XamlIlNotSelector(result, Create(not.Argument, typeResolver));
                        break;

                    case SelectorGrammar.CommaSyntax comma:
                        if (results == null)
                        {
                            results = new XamlIlOrSelectorNode(node, selectorType);
                        }
                        results.Add(result);
                        result = initialNode;
                        break;

                    default:
                        throw new XamlIlParseException($"Unsupported selector grammar '{i.GetType()}'.", node);
                    }
                }

                if (results != null && result != null)
                {
                    results.Add(result);
                }

                return(results ?? result);
            }

            IEnumerable <SelectorGrammar.ISyntax> parsed;

            try
            {
                parsed = SelectorGrammar.Parse(tn.Text);
            }
            catch (Exception e)
            {
                throw new XamlIlParseException("Unable to parse selector: " + e.Message, node);
            }

            var selector = Create(parsed, (p, n)
                                  => XamlIlTypeReferenceResolver.ResolveType(context, $"{p}:{n}", true, node, true));

            pn.Values[0] = selector;

            return(new AvaloniaXamlIlTargetTypeMetadataNode(on,
                                                            new XamlIlAstClrTypeReference(selector, selector.TargetType, false),
                                                            AvaloniaXamlIlTargetTypeMetadataNode.ScopeTypes.Style));
        }
示例#24
0
 public void NthChild_Invalid_Inputs(string input)
 {
     Assert.Throws <ExpressionParseException>(() => SelectorGrammar.Parse(input));
 }
示例#25
0
 public void Not_Without_Closing_Parenthesis_Fails()
 {
     Assert.Throws <ExpressionParseException>(() => SelectorGrammar.Parse(":not(Button"));
 }
示例#26
0
 public void Not_Without_Argument_Fails()
 {
     Assert.Throws <ExpressionParseException>(() => SelectorGrammar.Parse(":not()"));
 }
示例#27
0
 public void Invalid_Class_Fails()
 {
     Assert.Throws <ExpressionParseException>(() => SelectorGrammar.Parse(".%foo"));
 }
示例#28
0
 public void Invalid_Identifier_Fails()
 {
     Assert.Throws <ExpressionParseException>(() => SelectorGrammar.Parse("%foo"));
 }
示例#29
0
 public void Dot_Alone_Fails()
 {
     Assert.Throws <ExpressionParseException>(() => SelectorGrammar.Parse(". dot"));
 }
示例#30
0
 public void Namespace_Alone_Fails()
 {
     Assert.Throws <ExpressionParseException>(() => SelectorGrammar.Parse("ns|"));
 }