aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/algo/walk.rs
blob: 8e294d965b01dfdb9256c68ff7e9289a1ac8dc6a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
use {
    SyntaxNodeRef,
    algo::generate,
};


#[derive(Debug, Copy, Clone)]
pub enum WalkEvent<'a> {
    Enter(SyntaxNodeRef<'a>),
    Exit(SyntaxNodeRef<'a>),
}

pub fn walk<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = WalkEvent<'a>> {
    generate(Some(WalkEvent::Enter(root)), move |pos| {
        let next = match *pos {
            WalkEvent::Enter(node) => match node.first_child() {
                Some(child) => WalkEvent::Enter(child),
                None => WalkEvent::Exit(node),
            },
            WalkEvent::Exit(node) => {
                if node == root {
                    return None;
                }
                match node.next_sibling() {
                    Some(sibling) => WalkEvent::Enter(sibling),
                    None => WalkEvent::Exit(node.parent().unwrap()),
                }
            }
        };
        Some(next)
    })
}