aboutsummaryrefslogtreecommitdiff
path: root/src/utils.rs
blob: 1fbb872a534f058e2cbf4ef0552eaff59c5ccc53 (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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
use std::fmt::Write;
use {
    algo::walk::{walk, WalkEvent},
    SyntaxNode,
};

/// Parse a file and create a string representation of the resulting parse tree.
pub fn dump_tree(syntax: &SyntaxNode) -> String {
    let syntax = syntax.as_ref();
    let mut errors: Vec<_> = syntax.root.errors.iter().cloned().collect();
    errors.sort_by_key(|e| e.offset);
    let mut err_pos = 0;
    let mut level = 0;
    let mut buf = String::new();
    macro_rules! indent {
        () => {
            for _ in 0..level {
                buf.push_str("  ");
            }
        };
    }

    for event in walk(syntax) {
        match event {
            WalkEvent::Enter(node) => {
                indent!();
                writeln!(buf, "{:?}", node).unwrap();
                if node.first_child().is_none() {
                    let off = node.range().end();
                    while err_pos < errors.len() && errors[err_pos].offset <= off {
                        indent!();
                        writeln!(buf, "err: `{}`", errors[err_pos].msg).unwrap();
                        err_pos += 1;
                    }
                }
                level += 1;
            }
            WalkEvent::Exit(_) => level -= 1,
        }
    }

    assert_eq!(level, 0);
    for err in errors[err_pos..].iter() {
        writeln!(buf, "err: `{}`", err.msg).unwrap();
    }

    return buf;
}