Browse Source

Validate presence of nesting selector.

pull/8024/head
Steven Kirk 4 years ago
parent
commit
33679377f8
  1. 1
      src/Avalonia.Base/Styling/ChildSelector.cs
  2. 1
      src/Avalonia.Base/Styling/DescendentSelector.cs
  3. 1
      src/Avalonia.Base/Styling/NestingSelector.cs
  4. 1
      src/Avalonia.Base/Styling/NotSelector.cs
  5. 1
      src/Avalonia.Base/Styling/NthChildSelector.cs
  6. 13
      src/Avalonia.Base/Styling/OrSelector.cs
  7. 1
      src/Avalonia.Base/Styling/PropertyEqualsSelector.cs
  8. 2
      src/Avalonia.Base/Styling/Selector.cs
  9. 5
      src/Avalonia.Base/Styling/Style.cs
  10. 6
      src/Avalonia.Base/Styling/StyleChildren.cs
  11. 1
      src/Avalonia.Base/Styling/TemplateSelector.cs
  12. 1
      src/Avalonia.Base/Styling/TypeNameAndClassSelector.cs
  13. 42
      tests/Avalonia.Base.UnitTests/Styling/SelectorTests_Nesting.cs

1
src/Avalonia.Base/Styling/ChildSelector.cs

@ -65,5 +65,6 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => null;
internal override bool HasValidNestingSelector() => _parent.HasValidNestingSelector();
}
}

1
src/Avalonia.Base/Styling/DescendentSelector.cs

@ -70,5 +70,6 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => null;
internal override bool HasValidNestingSelector() => _parent.HasValidNestingSelector();
}
}

1
src/Avalonia.Base/Styling/NestingSelector.cs

@ -25,5 +25,6 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => null;
internal override bool HasValidNestingSelector() => true;
}
}

1
src/Avalonia.Base/Styling/NotSelector.cs

@ -67,5 +67,6 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => _previous;
internal override bool HasValidNestingSelector() => _argument.HasValidNestingSelector();
}
}

1
src/Avalonia.Base/Styling/NthChildSelector.cs

@ -105,6 +105,7 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => _previous;
internal override bool HasValidNestingSelector() => _previous?.HasValidNestingSelector() ?? false;
public override string ToString()
{

13
src/Avalonia.Base/Styling/OrSelector.cs

@ -104,6 +104,19 @@ namespace Avalonia.Styling
protected override Selector? MovePrevious() => null;
internal override bool HasValidNestingSelector()
{
foreach (var selector in _selectors)
{
if (!selector.HasValidNestingSelector())
{
return false;
}
}
return true;
}
private Type? EvaluateTargetType()
{
Type? result = null;

1
src/Avalonia.Base/Styling/PropertyEqualsSelector.cs

@ -90,6 +90,7 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => _previous;
internal override bool HasValidNestingSelector() => _previous?.HasValidNestingSelector() ?? false;
internal static bool Compare(Type propertyType, object? propertyValue, object? value)
{

2
src/Avalonia.Base/Styling/Selector.cs

@ -86,6 +86,8 @@ namespace Avalonia.Styling
/// </summary>
protected abstract Selector? MovePrevious();
internal abstract bool HasValidNestingSelector();
private static SelectorMatch MatchUntilCombinator(
IStyleable control,
Selector start,

5
src/Avalonia.Base/Styling/Style.cs

@ -186,8 +186,9 @@ namespace Avalonia.Styling
if (parent?.Selector is not null)
{
if (Selector is null)
throw new InvalidOperationException("Nested styles must have a selector.");
// TODO: Validate that selector contains & in the right place.
throw new InvalidOperationException("Child styles must have a selector.");
if (!Selector.HasValidNestingSelector())
throw new InvalidOperationException("Child styles must have a nesting selector.");
}
Parent = parent;

6
src/Avalonia.Base/Styling/StyleChildren.cs

@ -11,23 +11,23 @@ namespace Avalonia.Styling
protected override void InsertItem(int index, IStyle item)
{
base.InsertItem(index, item);
(item as Style)?.SetParent(_owner);
base.InsertItem(index, item);
}
protected override void RemoveItem(int index)
{
var item = Items[index];
(item as Style)?.SetParent(null);
if (_owner.Owner is IResourceHost host)
(item as IResourceProvider)?.RemoveOwner(host);
(item as Style)?.SetParent(null);
base.RemoveItem(index);
}
protected override void SetItem(int index, IStyle item)
{
base.SetItem(index, item);
(item as Style)?.SetParent(_owner);
base.SetItem(index, item);
if (_owner.Owner is IResourceHost host)
(item as IResourceProvider)?.AddOwner(host);
}

1
src/Avalonia.Base/Styling/TemplateSelector.cs

@ -49,5 +49,6 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => null;
internal override bool HasValidNestingSelector() => _parent?.HasValidNestingSelector() ?? false;
}
}

1
src/Avalonia.Base/Styling/TypeNameAndClassSelector.cs

@ -140,6 +140,7 @@ namespace Avalonia.Styling
}
protected override Selector? MovePrevious() => _previous;
internal override bool HasValidNestingSelector() => _previous?.HasValidNestingSelector() ?? false;
private string BuildSelectorString()
{

42
tests/Avalonia.Base.UnitTests/Styling/SelectorTests_Nesting.cs

@ -219,6 +219,48 @@ namespace Avalonia.Base.UnitTests.Styling
Assert.Throws<InvalidOperationException>(() => nested.Selector.Match(control, parent));
}
[Fact]
public void Adding_Child_With_No_Nesting_Selector_Fails()
{
var control = new Control1();
var parent = new Style(x => x.OfType<Control1>());
var child = new Style(x => x.Class("foo"));
Assert.Throws<InvalidOperationException>(() => parent.Children.Add(child));
}
[Fact]
public void Adding_Combinator_Selector_Child_With_No_Nesting_Selector_Fails()
{
var control = new Control1();
var parent = new Style(x => x.OfType<Control1>());
var child = new Style(x => x.Class("foo").Descendant().Class("bar"));
Assert.Throws<InvalidOperationException>(() => parent.Children.Add(child));
}
[Fact]
public void Adding_Or_Selector_Child_With_No_Nesting_Selector_Fails()
{
var control = new Control1();
var parent = new Style(x => x.OfType<Control1>());
var child = new Style(x => Selectors.Or(
x.Nesting().Class("foo"),
x.Class("bar")));
Assert.Throws<InvalidOperationException>(() => parent.Children.Add(child));
}
[Fact]
public void Can_Add_Child_Without_Nesting_Selector_To_Style_Without_Selector()
{
var control = new Control1();
var parent = new Style();
var child = new Style(x => x.Class("foo"));
parent.Children.Add(child);
}
public class Control1 : Control
{
}

Loading…
Cancel
Save