tree_sitter_utils/combinators/for_children.rs
1//! The [`ForChildren`] and [`ScanChildren`] combinators — apply a handler to
2//! every child of the current node and collect results.
3//!
4//! These combinators address the "iterate over children and dispatch each one
5//! through a kind table" pattern that appears throughout symbol-collection
6//! and inlay-hint traversals.
7//!
8//! ## Two variants
9//!
10//! | Combinator | Collects | When to use |
11//! |---|---|---|
12//! | [`ForChildren`] | `Vec<R>` of all `Some` results | Collect every matching child result into one `Vec`. |
13//! | [`ScanChildren`] | First `Some` result | Stop at the first child for which the handler succeeds. |
14//!
15//! Both variants operate on **named children only** by default (i.e. they
16//! call `node.named_children()`). The traversal is shallow — grandchildren
17//! are not visited; compose with [`Climb`](super::climb::Climb) or recurse
18//! manually if deep traversal is required.
19
20use crate::handler::{Handler, HandlerResult};
21use crate::input::Input;
22
23// ---------------------------------------------------------------------------
24// ForChildren
25// ---------------------------------------------------------------------------
26
27/// A handler that runs `inner` against every **named child** of the current
28/// node, collects all `Some(r)` results into a `Vec<R>`, and returns
29/// `Some(vec)` (which may be empty). It never returns `None`.
30///
31/// This makes it easy to replace `for child in node.named_children(...)` +
32/// `match child.kind() { ... }` loops with a composable handler chain.
33///
34/// Constructed via
35/// [`HandlerExt::for_children`](crate::HandlerExt::for_children).
36///
37/// # Example
38///
39/// ```rust
40/// use tree_sitter_utils::{handler_fn, HandlerExt, Input};
41///
42/// // Collect the kind-string of every named child.
43/// let h = handler_fn(|inp: Input<()>| inp.node.kind().to_owned())
44/// .for_children();
45/// let _ = h;
46/// ```
47pub struct ForChildren<H> {
48 /// The handler applied to each named child.
49 pub inner: H,
50}
51
52impl<Ctx, R, H> Handler<Ctx, Vec<R>> for ForChildren<H>
53where
54 H: Handler<Ctx, R>,
55 Ctx: Copy,
56{
57 fn handle<'tree>(&self, input: Input<'tree, Ctx>) -> HandlerResult<Vec<R>> {
58 let mut results = Vec::new();
59 let mut walker = input.node.walk();
60 for child in input.node.named_children(&mut walker) {
61 if let Some(r) = self.inner.handle(input.with_node(child)) {
62 results.push(r);
63 }
64 }
65 Some(results)
66 }
67}
68
69// ---------------------------------------------------------------------------
70// ScanChildren
71// ---------------------------------------------------------------------------
72
73/// A handler that runs `inner` against each **named child** of the current
74/// node in order, returning the **first** `Some(r)` result.
75///
76/// If no child produces `Some`, `ScanChildren` returns `None`.
77///
78/// Constructed via
79/// [`HandlerExt::scan_children`](crate::HandlerExt::scan_children).
80///
81/// # Example
82///
83/// ```rust
84/// use tree_sitter_utils::{handler_fn, HandlerExt, Input};
85///
86/// // Return the kind of the first named child that is an "identifier".
87/// let h = (|inp: Input<()>| -> Option<String> {
88/// (inp.node.kind() == "identifier").then(|| inp.node.kind().to_owned())
89/// })
90/// .scan_children();
91/// let _ = h;
92/// ```
93pub struct ScanChildren<H> {
94 /// The handler applied to each named child.
95 pub inner: H,
96}
97
98impl<Ctx, R, H> Handler<Ctx, R> for ScanChildren<H>
99where
100 H: Handler<Ctx, R>,
101 Ctx: Copy,
102{
103 fn handle<'tree>(&self, input: Input<'tree, Ctx>) -> HandlerResult<R> {
104 let mut walker = input.node.walk();
105 for child in input.node.named_children(&mut walker) {
106 if let Some(r) = self.inner.handle(input.with_node(child)) {
107 return Some(r);
108 }
109 }
110 None
111 }
112}