tree_sitter_utils/combinators.rs
1//! Combinator extension trait and sub-modules.
2//!
3//! Import [`HandlerExt`] to unlock all combinator methods on any [`Handler`].
4
5pub mod and_then;
6pub mod boxed;
7pub mod climb;
8pub mod find_ancestor;
9pub mod for_children;
10pub mod map;
11pub mod or;
12pub mod when;
13
14use std::marker::PhantomData;
15
16use crate::handler::Handler;
17use crate::input::Input;
18use crate::predicates::{kind_is, KindIs, NodePredicate};
19
20use self::and_then::AndThen;
21use self::boxed::BoxedHandler;
22use self::climb::{Climb, OrElseClimb};
23use self::find_ancestor::FindAncestor;
24use self::for_children::{ForChildren, ScanChildren};
25use self::map::Map;
26use self::or::Or;
27use self::when::When;
28
29/// Extension trait that adds combinator methods to every [`Handler`].
30///
31/// Blanket-implemented for all `T: Handler<Ctx, R>`; not intended as a trait
32/// object.
33///
34/// # Example
35///
36/// ```rust
37/// use tree_sitter_utils::{handler_fn, HandlerExt, Input, never};
38///
39/// let h = never::<(), u32>()
40/// .or(handler_fn(|_: Input<()>| 42u32))
41/// .map(|n| n.to_string());
42/// let _ = h;
43/// ```
44pub trait HandlerExt<Ctx, R>: Handler<Ctx, R> + Sized {
45 /// Try `self`; if it returns `None`, try `other`.
46 ///
47 /// # Example
48 ///
49 /// ```rust
50 /// use tree_sitter_utils::{never, handler_fn, HandlerExt, Input};
51 ///
52 /// let h = never::<(), String>()
53 /// .or(handler_fn(|_: Input<()>| "fallback".to_owned()));
54 /// let _ = h;
55 /// ```
56 fn or<H: Handler<Ctx, R>>(self, other: H) -> Or<Self, H> {
57 Or { first: self, second: other }
58 }
59
60 /// Run `self` only when `pred` returns `true`; otherwise return `None`.
61 ///
62 /// # Example
63 ///
64 /// ```rust
65 /// use tree_sitter_utils::{handler_fn, HandlerExt, kind_is, Input};
66 ///
67 /// let h = handler_fn(|_: Input<()>| "hit".to_owned())
68 /// .when(kind_is(&["identifier"]));
69 /// let _ = h;
70 /// ```
71 fn when<P: NodePredicate<Ctx>>(self, pred: P) -> When<Self, P> {
72 When { inner: self, pred }
73 }
74
75 /// Sugar for `.when(kind_is(kinds))` - only handle specific node kinds.
76 ///
77 /// # Example
78 ///
79 /// ```rust
80 /// use tree_sitter_utils::{handler_fn, HandlerExt, Input};
81 ///
82 /// let h = handler_fn(|_: Input<()>| "ident".to_owned())
83 /// .for_kinds(&["identifier", "type_identifier"]);
84 /// let _ = h;
85 /// ```
86 fn for_kinds(self, kinds: &'static [&'static str]) -> When<Self, KindIs> {
87 self.when(kind_is(kinds))
88 }
89
90 /// Apply `f` to the output value when `self` succeeds.
91 ///
92 /// # Example
93 ///
94 /// ```rust
95 /// use tree_sitter_utils::{handler_fn, HandlerExt, Input};
96 ///
97 /// let h = handler_fn(|_: Input<()>| 1u32).map(|n| n.to_string());
98 /// let _ = h;
99 /// ```
100 fn map<F, R2>(self, f: F) -> Map<Self, F, R>
101 where
102 F: Fn(R) -> R2 + Send + Sync,
103 {
104 Map { inner: self, f, _marker: PhantomData }
105 }
106
107 /// Transform the [`Input`] before passing it to `self`.
108 ///
109 /// # Example
110 ///
111 /// ```rust
112 /// use tree_sitter_utils::{handler_fn, HandlerExt, Input};
113 ///
114 /// let h = handler_fn(|input: Input<()>| input.node.kind().to_owned())
115 /// .map_input(|mut i: Input<()>| { i.trigger_char = Some('.'); i });
116 /// let _ = h;
117 /// ```
118 fn map_input<F>(self, f: F) -> MapInput<Self, F>
119 where
120 F: for<'tree> Fn(Input<'tree, Ctx>) -> Input<'tree, Ctx> + Send + Sync,
121 {
122 MapInput { inner: self, f }
123 }
124
125 /// On success, pass `(input, out)` to `f`, which may itself return `None`.
126 ///
127 /// # Example
128 ///
129 /// ```rust
130 /// use tree_sitter_utils::{handler_fn, HandlerExt, Input};
131 ///
132 /// let h = handler_fn(|_: Input<()>| 1u32)
133 /// .and_then(|_: Input<()>, n: u32| Some(n + 1));
134 /// let _ = h;
135 /// ```
136 fn and_then<F, R2>(self, f: F) -> AndThen<Self, F, R>
137 where
138 F: Fn(Input<'_, Ctx>, R) -> Option<R2> + Send + Sync,
139 {
140 AndThen { inner: self, f, _marker: PhantomData }
141 }
142
143 /// Retry `self` on each ancestor until it succeeds, stopping at any kind
144 /// in `stop_kinds` or at the root.
145 ///
146 /// # Example
147 ///
148 /// ```rust
149 /// use tree_sitter_utils::{handler_fn, HandlerExt, Input};
150 ///
151 /// let h = handler_fn(|input: Input<()>| {
152 /// (input.node.kind() == "module").then(|| "module".to_owned())
153 /// })
154 /// .climb(&["source_file"]);
155 /// let _ = h;
156 /// ```
157 fn climb(self, stop_kinds: &'static [&'static str]) -> Climb<Self> {
158 Climb { inner: self, stop_kinds }
159 }
160
161 /// Try `self` on the original node; on `None`, try `other` on each ancestor.
162 ///
163 /// # Example
164 ///
165 /// ```rust
166 /// use tree_sitter_utils::{never, HandlerExt, Input};
167 ///
168 /// let h = never::<(), String>()
169 /// .or_else_climb(
170 /// |input: tree_sitter_utils::Input<()>| -> Option<String> {
171 /// Some(input.node.kind().to_owned())
172 /// },
173 /// &["source_file"],
174 /// );
175 /// let _ = h;
176 /// ```
177 fn or_else_climb<O: Handler<Ctx, R>>(self, other: O, stop_kinds: &'static [&'static str]) -> OrElseClimb<Self, O> {
178 OrElseClimb { inner: self, other, stop_kinds }
179 }
180
181 /// Walk up to the nearest strict ancestor in `target_kinds`, then run
182 /// `self` on **that ancestor node** once.
183 ///
184 /// Unlike [`HandlerExt::climb`], which retries `self` on every ancestor,
185 /// `find_ancestor` locates a specific kind first and invokes `self` once.
186 ///
187 /// Stops (`None`) when a `stop_kinds` node or the root is reached.
188 ///
189 /// # Example
190 ///
191 /// ```rust
192 /// use tree_sitter_utils::{handler_fn, HandlerExt, Input};
193 ///
194 /// let h = handler_fn(|inp: Input<()>| inp.node.kind().to_owned())
195 /// .find_ancestor(&["argument_list"], &["program"]);
196 /// let _ = h;
197 /// ```
198 fn find_ancestor(self, target_kinds: &'static [&'static str], stop_kinds: &'static [&'static str]) -> FindAncestor<Self> {
199 FindAncestor { inner: self, target_kinds, stop_kinds }
200 }
201
202 /// Apply `self` to every **named child**, collect all `Some(r)` into a
203 /// `Vec<R>`, and return `Some(vec)` (never `None`).
204 ///
205 /// # Example
206 ///
207 /// ```rust
208 /// use tree_sitter_utils::{handler_fn, HandlerExt, Input};
209 ///
210 /// let h = handler_fn(|inp: Input<()>| inp.node.kind().to_owned())
211 /// .for_children();
212 /// let _ = h;
213 /// ```
214 fn for_children(self) -> ForChildren<Self> {
215 ForChildren { inner: self }
216 }
217
218 /// Apply `self` to each **named child** in order; return the first
219 /// `Some(r)`, or `None` if no child matches.
220 ///
221 /// # Example
222 ///
223 /// ```rust
224 /// use tree_sitter_utils::{Input, HandlerExt};
225 ///
226 /// let h = (|inp: Input<()>| -> Option<String> {
227 /// (inp.node.kind() == "identifier").then(|| inp.node.kind().to_owned())
228 /// })
229 /// .scan_children();
230 /// let _ = h;
231 /// ```
232 fn scan_children(self) -> ScanChildren<Self> {
233 ScanChildren { inner: self }
234 }
235
236 /// Erase the concrete type into a [`BoxedHandler`] for dynamic dispatch.
237 ///
238 /// # Example
239 ///
240 /// ```rust
241 /// use tree_sitter_utils::{handler_fn, HandlerExt, BoxedHandler, Input};
242 ///
243 /// let h: BoxedHandler<(), String> =
244 /// handler_fn(|_: Input<()>| "hi".to_owned()).boxed();
245 /// let _ = h;
246 /// ```
247 fn boxed(self) -> BoxedHandler<Ctx, R>
248 where
249 Self: 'static,
250 Ctx: Copy,
251 {
252 BoxedHandler::new(move |input| self.handle(input))
253 }
254}
255
256impl<Ctx, R, T: Handler<Ctx, R>> HandlerExt<Ctx, R> for T {}
257
258pub struct MapInput<H, F> {
259 pub inner: H,
260 pub f: F,
261}
262
263impl<Ctx, R, H, F> Handler<Ctx, R> for MapInput<H, F>
264where
265 H: Handler<Ctx, R>,
266 F: for<'tree> Fn(Input<'tree, Ctx>) -> Input<'tree, Ctx> + Send + Sync,
267 Ctx: Copy,
268{
269 #[inline]
270 fn handle<'tree>(&self, input: Input<'tree, Ctx>) -> Option<R> {
271 self.inner.handle((self.f)(input))
272 }
273}