Skip to main content

cxx2flow_lib/
dump.rs

1use std::collections::HashMap;
2
3use colored::*;
4use itertools::Itertools;
5use tree_sitter::{Node, TreeCursor};
6
7pub fn useful_children<'a, 'tree>(
8    node: &'a Node<'tree>,
9    cursor: &'a mut TreeCursor<'tree>,
10) -> impl Iterator<Item = Node<'tree>> + 'a {
11    node.children(cursor).enumerate().filter_map(move |(i, n)| {
12        if n.is_named() || node.field_name_for_child(i as u32).is_some() {
13            Some(n)
14        } else {
15            None
16        }
17    })
18}
19
20#[allow(dead_code)]
21fn dump_node_internal(
22    node: &Node,
23    prefix: &str,
24    content: &[u8],
25    field_name: Option<&str>,
26    is_last: bool,
27    is_init: bool,
28) {
29    let node_text = node.utf8_text(content).unwrap();
30    let start = node.start_position();
31    let end = node.end_position();
32    let kind = node.kind();
33    println!(
34        "{}{}{}: `{}` {} - {}{}",
35        prefix,
36        if is_init {
37            ""
38        } else if is_last {
39            "└──"
40        } else {
41            "├──"
42        },
43        match field_name {
44            Some(name) => name.bold().yellow(),
45            None => "[ANON]".normal(),
46        },
47        kind.bold(),
48        start,
49        end,
50        if node.child_count() == 0 || !node_text.contains('\n') {
51            format!(" {} {}", "->".cyan(), node_text.bold()).bold()
52        } else {
53            "".to_owned().normal()
54        }
55    );
56    let node_to_idx: HashMap<_, _> = {
57        let mut cursor = node.walk();
58        node.children(&mut cursor)
59            .enumerate()
60            .map(|(x, y)| (y, x))
61            .collect()
62    };
63    let nodes: Vec<_> = {
64        let mut cursor = node.walk();
65        // useful_children(node, &mut cursor).collect_vec()
66        node.children(&mut cursor).collect_vec()
67    };
68    let prefix = format!("{}{}   ", prefix, if is_last { " " } else { "│" });
69    for (pos, i) in nodes.into_iter().with_position() {
70        match pos {
71            itertools::Position::First | itertools::Position::Middle => {
72                dump_node_internal(
73                    &i,
74                    &prefix,
75                    content,
76                    node.field_name_for_child(node_to_idx[&i] as u32),
77                    false,
78                    false,
79                );
80            }
81            itertools::Position::Last | itertools::Position::Only => {
82                dump_node_internal(
83                    &i,
84                    &prefix,
85                    content,
86                    node.field_name_for_child(node_to_idx[&i] as u32),
87                    true,
88                    false,
89                );
90            }
91        }
92    }
93}
94
95#[allow(dead_code)]
96pub fn dump_node(node: &Node, content: &[u8]) {
97    dump_node_internal(node, "", content, None, true, true);
98}