rust_code_analysis/output/
dump_ops.rs

1use std::io::Write;
2use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, StandardStreamLock, WriteColor};
3
4use crate::ops::Ops;
5
6/// Dumps all operands and operators of a code.
7///
8/// Returns a [`Result`] value, when an error occurs.
9///
10/// # Examples
11///
12/// ```
13/// use std::path::PathBuf;
14///
15/// use rust_code_analysis::{dump_ops, operands_and_operators, CppParser, ParserTrait};
16///
17/// # fn main() {
18/// let source_code = "int a = 42;";
19///
20/// // The path to a dummy file used to contain the source code
21/// let path = PathBuf::from("foo.c");
22/// let source_as_vec = source_code.as_bytes().to_vec();
23///
24/// // The parser of the code, in this case a CPP parser
25/// let parser = CppParser::new(source_as_vec, &path, None);
26///
27/// // Retrieve all operands and operators
28/// let ops = operands_and_operators(&parser, &path).unwrap();
29///
30/// // Dump all operands and operators
31/// dump_ops(&ops).unwrap();
32/// # }
33/// ```
34///
35/// [`Result`]: #variant.Result
36pub fn dump_ops(ops: &Ops) -> std::io::Result<()> {
37    let stdout = StandardStream::stdout(ColorChoice::Always);
38    let mut stdout = stdout.lock();
39    dump_space(ops, "", true, &mut stdout)?;
40    color!(stdout, White);
41
42    Ok(())
43}
44
45fn dump_space(
46    space: &Ops,
47    prefix: &str,
48    last: bool,
49    stdout: &mut StandardStreamLock,
50) -> std::io::Result<()> {
51    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
52
53    color!(stdout, Blue);
54    write!(stdout, "{}{}", prefix, pref)?;
55
56    color!(stdout, Yellow, true);
57    write!(stdout, "{}: ", space.kind)?;
58
59    color!(stdout, Cyan, true);
60    write!(stdout, "{}", space.name.as_ref().map_or("", |name| name))?;
61
62    color!(stdout, Red, true);
63    writeln!(stdout, " (@{})", space.start_line)?;
64
65    let prefix = format!("{}{}", prefix, pref_child);
66    dump_space_ops(space, &prefix, space.spaces.is_empty(), stdout)?;
67
68    if let Some((last, spaces)) = space.spaces.split_last() {
69        for space in spaces {
70            dump_space(space, &prefix, false, stdout)?;
71        }
72        dump_space(last, &prefix, true, stdout)?;
73    }
74
75    Ok(())
76}
77
78fn dump_space_ops(
79    ops: &Ops,
80    prefix: &str,
81    last: bool,
82    stdout: &mut StandardStreamLock,
83) -> std::io::Result<()> {
84    dump_ops_values("operators", &ops.operators, prefix, last, stdout)?;
85    dump_ops_values("operands", &ops.operands, prefix, last, stdout)
86}
87
88fn dump_ops_values(
89    name: &str,
90    ops: &[String],
91    prefix: &str,
92    last: bool,
93    stdout: &mut StandardStreamLock,
94) -> std::io::Result<()> {
95    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
96
97    color!(stdout, Blue);
98    write!(stdout, "{}{}", prefix, pref)?;
99
100    color!(stdout, Green, true);
101    writeln!(stdout, "{}", name)?;
102
103    let prefix = format!("{}{}", prefix, pref_child);
104    for op in ops.iter().take(ops.len() - 1) {
105        color!(stdout, Blue);
106        write!(stdout, "{}|- ", prefix)?;
107
108        color!(stdout, White);
109        writeln!(stdout, "{}", op)?;
110    }
111
112    color!(stdout, Blue);
113    write!(stdout, "{}`- ", prefix)?;
114
115    color!(stdout, White);
116    writeln!(stdout, "{}", ops.last().unwrap())
117}