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 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}