rust_code_analysis_code_split/output/
dump.rs1use std::io::Write;
2
3use termcolor::{Color, ColorChoice, StandardStream, StandardStreamLock};
4
5use crate::node::Node;
6use crate::tools::{color, intense_color};
7
8use crate::traits::*;
9
10pub fn dump_node(
39 code: &[u8],
40 node: &Node,
41 depth: i32,
42 line_start: Option<usize>,
43 line_end: Option<usize>,
44) -> std::io::Result<()> {
45 let stdout = StandardStream::stdout(ColorChoice::Always);
46 let mut stdout = stdout.lock();
47 let ret = dump_tree_helper(
48 code,
49 node,
50 "",
51 true,
52 &mut stdout,
53 depth,
54 &line_start,
55 &line_end,
56 );
57
58 color(&mut stdout, Color::White)?;
59
60 ret
61}
62
63#[allow(clippy::too_many_arguments)]
64fn dump_tree_helper(
65 code: &[u8],
66 node: &Node,
67 prefix: &str,
68 last: bool,
69 stdout: &mut StandardStreamLock,
70 depth: i32,
71 line_start: &Option<usize>,
72 line_end: &Option<usize>,
73) -> std::io::Result<()> {
74 if depth == 0 {
75 return Ok(());
76 }
77
78 let (pref_child, pref) = if node.parent().is_none() {
79 ("", "")
80 } else if last {
81 (" ", "╰─ ")
82 } else {
83 ("│ ", "├─ ")
84 };
85
86 let node_row = node.start_row() + 1;
87 let mut display = true;
88 if let Some(line_start) = line_start {
89 display = node_row >= *line_start
90 }
91 if let Some(line_end) = line_end {
92 display = display && node_row <= *line_end
93 }
94
95 if display {
96 color(stdout, Color::Blue)?;
97 write!(stdout, "{prefix}{pref}")?;
98
99 intense_color(stdout, Color::Yellow)?;
100 write!(stdout, "{{{}:{}}} ", node.kind(), node.kind_id())?;
101
102 color(stdout, Color::White)?;
103 write!(stdout, "from ")?;
104
105 color(stdout, Color::Green)?;
106 let (pos_row, pos_column) = node.start_position();
107 write!(stdout, "({}, {}) ", pos_row + 1, pos_column + 1)?;
108
109 color(stdout, Color::White)?;
110 write!(stdout, "to ")?;
111
112 color(stdout, Color::Green)?;
113 let (pos_row, pos_column) = node.end_position();
114 write!(stdout, "({}, {}) ", pos_row + 1, pos_column + 1)?;
115
116 if node.start_row() == node.end_row() {
117 color(stdout, Color::White)?;
118 write!(stdout, ": ")?;
119
120 intense_color(stdout, Color::Red)?;
121 let code = &code[node.start_byte()..node.end_byte()];
122 if let Ok(code) = String::from_utf8(code.to_vec()) {
123 write!(stdout, "{code} ")?;
124 } else {
125 stdout.write_all(code).unwrap();
126 }
127 }
128
129 writeln!(stdout)?;
130 }
131
132 let count = node.child_count();
133 if count != 0 {
134 let prefix = format!("{prefix}{pref_child}");
135 let mut i = count;
136 let mut cursor = node.cursor();
137 cursor.goto_first_child();
138
139 loop {
140 i -= 1;
141 dump_tree_helper(
142 code,
143 &cursor.node(),
144 &prefix,
145 i == 0,
146 stdout,
147 depth - 1,
148 line_start,
149 line_end,
150 )?;
151 if !cursor.goto_next_sibling() {
152 break;
153 }
154 }
155 }
156
157 Ok(())
158}
159
160#[derive(Debug)]
162pub struct DumpCfg {
163 pub line_start: Option<usize>,
168 pub line_end: Option<usize>,
173}
174
175pub struct Dump {
176 _guard: (),
177}
178
179impl Callback for Dump {
180 type Res = std::io::Result<()>;
181 type Cfg = DumpCfg;
182
183 fn call<T: ParserTrait>(cfg: Self::Cfg, parser: &T) -> Self::Res {
184 dump_node(
185 parser.get_code(),
186 &parser.get_root(),
187 -1,
188 cfg.line_start,
189 cfg.line_end,
190 )
191 }
192}