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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use std::collections::HashMap;
use colored::*;
use itertools::Itertools;
use tree_sitter::{Node, TreeCursor};
pub fn useful_children<'a, 'tree>(
node: &'a Node<'tree>,
cursor: &'a mut TreeCursor<'tree>,
) -> impl Iterator<Item = Node<'tree>> + 'a {
node.children(cursor).enumerate().filter_map(move |(i, n)| {
if n.is_named() || node.field_name_for_child(i as u32).is_some() {
Some(n)
} else {
None
}
})
}
#[allow(dead_code)]
fn dump_node_internal(
node: &Node,
prefix: &str,
content: &str,
field_name: Option<&str>,
is_last: bool,
is_init: bool,
) {
let node_text = node.utf8_text(content.as_bytes()).unwrap();
let start = node.start_position();
let end = node.end_position();
let kind = node.kind();
println!(
"{}{}{}: `{}` {} - {}{}",
prefix,
if is_init {
""
} else if is_last {
"└──"
} else {
"├──"
},
match field_name {
Some(name) => name.bold().yellow(),
None => "[ANON]".normal(),
},
kind.bold(),
start,
end,
if node.child_count() == 0 || !node_text.contains('\n') {
format!(" {} {}", "->".cyan(), node_text.bold()).bold()
} else {
"".to_owned().normal()
}
);
let node_to_idx: HashMap<_, _> = {
let mut cursor = node.walk();
node.children(&mut cursor)
.enumerate()
.map(|(x, y)| (y, x))
.collect()
};
let nodes: Vec<_> = {
let mut cursor = node.walk();
useful_children(node, &mut cursor).collect_vec()
};
let prefix = format!("{}{} ", prefix, if is_last { " " } else { "│" });
for i in nodes.into_iter().with_position() {
match i {
itertools::Position::First(n) | itertools::Position::Middle(n) => {
dump_node_internal(
&n,
&prefix,
content,
node.field_name_for_child(node_to_idx[&n] as u32),
false,
false,
);
}
itertools::Position::Last(n) | itertools::Position::Only(n) => {
dump_node_internal(
&n,
&prefix,
content,
node.field_name_for_child(node_to_idx[&n] as u32),
true,
false,
);
}
}
}
}
#[allow(dead_code)]
pub fn dump_node(node: &Node, content: &str) {
dump_node_internal(node, "", content, None, true, true);
}