Skip to content

Commit 349cebc

Browse files
committed
#30 Support ShouldListenToChildren in CompositeListeners.
1 parent fb27fb1 commit 349cebc

5 files changed

Lines changed: 51 additions & 3 deletions

File tree

doc/topics/API/MrKWatkins.Ast.Children-1.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
Collection of child nodes for a [Node<TNode>](MrKWatkins.Ast.Node-1.md).
55

66
```c#
7-
public sealed class Children<TNode> : IList<TNode>, ICollection<TNode>, IEnumerable<TNode>, IEnumerable
7+
public sealed class Children<TNode> : IList<TNode>, ICollection<TNode>, IEnumerable<TNode>, IEnumerable, IReadOnlyList<TNode>, IReadOnlyCollection<TNode>
88
where TNode : Node<TNode>
99
```
1010

src/MrKWatkins.Ast.Tests/Listening/CompositeListenerWithContextTests.cs renamed to src/MrKWatkins.Ast.Tests/Listening/CompositeListenerTests.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,35 @@ public void Listen_RootType()
152152
rootListener.Count.Should().Equal(10);
153153
}
154154

155+
[Test]
156+
public void Listen_ShouldListenToChildren()
157+
{
158+
var doListenToChildren = new TestListener<ANode> { ListenToChildren = (_, _) => true };
159+
var doNotListenToChildren = new TestListener<BNode> { ListenToChildren = (_, _) => false };
160+
161+
var tree = new ANode(new ANode(new CNode()), new BNode(new BChild()), new CNode());
162+
163+
var listener = CompositeListener<TestContext, TestNode>
164+
.Build()
165+
.With(doListenToChildren)
166+
.With(doNotListenToChildren)
167+
.ToListener();
168+
169+
var context = new TestContext();
170+
listener.Listen(context, tree);
171+
172+
context.Count.Should().Equal(3);
173+
doListenToChildren.Count.Should().Equal(2);
174+
doNotListenToChildren.Count.Should().Equal(1);
175+
176+
// Repeat to ensure cached handlers work.
177+
listener.Listen(context, tree);
178+
179+
context.Count.Should().Equal(6);
180+
doListenToChildren.Count.Should().Equal(4);
181+
doNotListenToChildren.Count.Should().Equal(2);
182+
}
183+
155184
private class BChild : BNode;
156185

157186
private class BGrandChild : BChild;
@@ -172,13 +201,17 @@ protected internal override void ListenToNode(TestContext context, TestNode _)
172201
private sealed class TestListener<TNode> : Listener<TestContext, TestNode, TNode>
173202
where TNode : TestNode
174203
{
204+
public Func<TestContext, TNode, bool>? ListenToChildren { get; init; }
205+
175206
public int Count { get; private set; }
176207

177208
protected override void ListenToNode(TestContext context, TNode _)
178209
{
179210
context.Count++;
180211
Count++;
181212
}
213+
214+
protected override bool ShouldListenToChildren(TestContext context, TNode node) => ListenToChildren?.Invoke(context, node) ?? base.ShouldListenToChildren(context, node);
182215
}
183216

184217
private sealed class TestContext

src/MrKWatkins.Ast.Tests/Listening/ListenerWithContextTests.cs renamed to src/MrKWatkins.Ast.Tests/Listening/ListenerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ private sealed class TestListener : Listener<StringBuilder, TestNode>
4242

4343
protected internal override void AfterListenToNode(StringBuilder context, TestNode node) => context.Append(')');
4444

45-
protected override bool ShouldListenToChildren(StringBuilder context, TestNode node) => ListenToChildren?.Invoke(context, node) ?? base.ShouldListenToChildren(context, node);
45+
protected internal override bool ShouldListenToChildren(StringBuilder context, TestNode node) => ListenToChildren?.Invoke(context, node) ?? base.ShouldListenToChildren(context, node);
4646
}
4747

4848
private sealed class CallsBaseTestListener : Listener<StringBuilder, TestNode>

src/MrKWatkins.Ast/Listening/CompositeListener.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ private CompositeListener()
3232
/// <inheritdoc />
3333
protected internal override void AfterListenToNode(TContext context, TBaseNode node) => listeners.Get(node)?.AfterListenToNode(context, node);
3434

35+
/// <inheritdoc />
36+
protected internal override bool ShouldListenToChildren(TContext context, TBaseNode node) => listeners.Get(node)?.ShouldListenToChildren(context, node) ?? true;
37+
3538
[MustUseReturnValue]
3639
ICompositeListenerBuilder<TContext, TBaseNode> ICompositeListenerBuilder<TContext, TBaseNode>.With(Listener<TContext, TBaseNode> listener)
3740
{

src/MrKWatkins.Ast/Listening/Listener.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ protected internal virtual void AfterListenToNode(TContext context, TNode node)
6868
/// <param name="context">The context object.</param>
6969
/// <param name="node">The node whose children should be listened to or not.</param>
7070
/// <returns><c>true</c> if child nodes should be listened to, <c>false</c> otherwise.</returns>
71-
protected virtual bool ShouldListenToChildren(TContext context, TNode node) => true;
71+
protected internal virtual bool ShouldListenToChildren(TContext context, TNode node) => true;
7272
}
7373

7474
/// <summary>
@@ -135,4 +135,16 @@ protected internal sealed override void AfterListenToNode(TContext context, TBas
135135
protected virtual void AfterListenToNode(TContext context, TNode node)
136136
{
137137
}
138+
139+
/// <inheritdoc />
140+
protected internal sealed override bool ShouldListenToChildren(TContext context, TBaseNode node) =>
141+
node is not TNode typedNode || ShouldListenToChildren(context, typedNode);
142+
143+
/// <summary>
144+
/// Return a value indicating whether child nodes should be listened to or not. Defaults to <c>true</c>.
145+
/// </summary>
146+
/// <param name="context">The context object.</param>
147+
/// <param name="node">The node whose children should be listened to or not.</param>
148+
/// <returns><c>true</c> if child nodes should be listened to, <c>false</c> otherwise.</returns>
149+
protected virtual bool ShouldListenToChildren(TContext context, TNode node) => true;
138150
}

0 commit comments

Comments
 (0)