Skip to main content

leekscript_tooling/
visitor.rs

1//! Generic visitor over the parsed `LeekScript` syntax tree.
2//!
3//! Re-exports sipha's tree walk ([`Visitor`], [`WalkOptions`], [`walk`], [`WalkResult`]).
4//! Implement [`Visitor`] and call [`walk`] (or `root.walk(...)`) with your visitor and options.
5
6// Re-export so callers can use one import from leekscript_rs.
7pub use sipha::walk::{Visitor, WalkOptions, WalkResult};
8
9/// Walks the tree starting at `root` with the given visitor and options.
10///
11/// Returns `ControlFlow::Break(())` if the visitor requested early termination.
12pub fn walk(
13    root: &sipha::red::SyntaxNode,
14    visitor: &mut impl sipha::walk::Visitor,
15    options: &WalkOptions,
16) -> WalkResult {
17    root.walk(visitor, options)
18}
19
20#[cfg(test)]
21mod tests {
22    use super::*;
23    use leekscript_core::parse;
24
25    struct CountNodes {
26        nodes: usize,
27        tokens: usize,
28    }
29
30    impl Visitor for CountNodes {
31        fn enter_node(&mut self, _node: &sipha::red::SyntaxNode) -> WalkResult {
32            self.nodes += 1;
33            WalkResult::Continue(())
34        }
35        fn visit_token(&mut self, _token: &sipha::red::SyntaxToken) -> WalkResult {
36            self.tokens += 1;
37            WalkResult::Continue(())
38        }
39    }
40
41    #[test]
42    fn visitor_walks_program() {
43        let source = "var x = 1; function f() { return x; }";
44        let root = parse(source).unwrap().expect("parse");
45        let mut counter = CountNodes {
46            nodes: 0,
47            tokens: 0,
48        };
49        let _ = walk(&root, &mut counter, &WalkOptions::default());
50        assert!(counter.nodes > 0, "should visit nodes");
51        assert!(counter.tokens > 0, "should visit tokens");
52    }
53
54    #[test]
55    fn nodes_only_visits_no_tokens() {
56        let source = "let a = 2;";
57        let root = parse(source).unwrap().expect("parse");
58        let mut counter = CountNodes {
59            nodes: 0,
60            tokens: 0,
61        };
62        let _ = walk(&root, &mut counter, &WalkOptions::nodes_only());
63        assert!(counter.nodes > 0);
64        assert_eq!(counter.tokens, 0);
65    }
66}