Skip to content

Commit ecffbba

Browse files
Fixed Selector.ValidateNestingSelector not calling overrides
Changed ValidateNestingSelector to call recursively walking up the hierarchy of parent selectors. This means function overrides are taken into account when walking up the tree. Now if a leaf selector has an OrSelector as its parent, the OrSelector doesn't throw an exception.
1 parent a533f5f commit ecffbba

File tree

3 files changed

+40
-20
lines changed

3 files changed

+40
-20
lines changed

src/Avalonia.Base/Styling/OrSelector.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,13 +97,13 @@ private protected override SelectorMatch Evaluate(StyledElement control, IStyle?
9797
private protected override Selector? MovePrevious() => null;
9898
private protected override Selector? MovePreviousOrParent() => null;
9999

100-
internal override void ValidateNestingSelector(bool inControlTheme)
100+
internal override void ValidateNestingSelector(bool inControlTheme, int templateCount = 0)
101101
{
102102
var count = _selectors.Count;
103103

104104
for (var i = 0; i < count; i++)
105105
{
106-
_selectors[i].ValidateNestingSelector(inControlTheme);
106+
_selectors[i].ValidateNestingSelector(inControlTheme, templateCount);
107107
}
108108
}
109109

src/Avalonia.Base/Styling/Selector.cs

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -100,30 +100,31 @@ internal SelectorMatch Match(StyledElement control, IStyle? parent = null, bool
100100
/// </summary>
101101
private protected abstract Selector? MovePreviousOrParent();
102102

103-
internal virtual void ValidateNestingSelector(bool inControlTheme)
103+
internal virtual void ValidateNestingSelector(bool inControlTheme, int templateCount = 0)
104104
{
105105
var s = this;
106-
var templateCount = 0;
107106

108-
do
107+
if (inControlTheme)
109108
{
110-
if (inControlTheme)
111-
{
112-
if (!s.InTemplate && s.IsCombinator)
113-
throw new InvalidOperationException(
114-
"ControlTheme style may not directly contain a child or descendent selector.");
115-
if (s is TemplateSelector && templateCount++ > 0)
116-
throw new InvalidOperationException(
117-
"ControlTemplate styles cannot contain multiple template selectors.");
118-
}
119-
120-
var previous = s.MovePreviousOrParent();
109+
if (!s.InTemplate && s.IsCombinator)
110+
throw new InvalidOperationException(
111+
"ControlTheme style may not directly contain a child or descendent selector.");
112+
if (s is TemplateSelector && templateCount++ > 0)
113+
throw new InvalidOperationException(
114+
"ControlTemplate styles cannot contain multiple template selectors.");
115+
}
116+
117+
var previous = s.MovePreviousOrParent();
121118

122-
if (previous is null && s is not NestingSelector)
119+
if (previous is null)
120+
{
121+
if (s is not NestingSelector)
123122
throw new InvalidOperationException("Child styles must have a nesting selector.");
124-
125-
s = previous;
126-
} while (s is not null);
123+
}
124+
else
125+
{
126+
previous.ValidateNestingSelector(inControlTheme, templateCount);
127+
}
127128
}
128129

129130
private static SelectorMatch MatchUntilCombinator(

tests/Avalonia.Base.UnitTests/Styling/SelectorTests_Or.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using Avalonia.Controls;
23
using Avalonia.Styling;
34
using Xunit;
@@ -89,6 +90,24 @@ public void Returns_Null_TargetType_When_A_Selector_Has_No_TargetType()
8990

9091
Assert.Equal(null, target.TargetType);
9192
}
93+
94+
[Fact]
95+
public void ValidateNestingSelector_Checks_Children_When_Parent_Is_An_OrSelector()
96+
{
97+
var target = Selectors.Or(
98+
default(Selector).Class("foo"),
99+
default(Selector).Class("bar")
100+
).Name("baz");
101+
102+
Assert.Throws<InvalidOperationException>(() => target.ValidateNestingSelector(false));
103+
104+
target = Selectors.Or(
105+
default(Selector).Nesting().Class("foo"),
106+
default(Selector).Nesting().Class("bar")
107+
).Name("baz");
108+
109+
target.ValidateNestingSelector(false);
110+
}
92111

93112
public class Control1 : Control
94113
{

0 commit comments

Comments
 (0)