Skip to main content

codelore_rca/output/
dump_metrics.rs

1use std::io::Write;
2use termcolor::{Color, ColorChoice, StandardStream, StandardStreamLock};
3
4use crate::cognitive;
5use crate::cyclomatic;
6use crate::exit;
7use crate::halstead;
8use crate::loc;
9use crate::mi;
10use crate::nargs;
11use crate::nom;
12
13use crate::spaces::{CodeMetrics, FuncSpace};
14
15use crate::tools::{color, intense_color};
16
17/// Dumps the metrics of a code.
18///
19/// Returns a [`Result`] value, when an error occurs.
20///
21/// # Examples
22///
23/// ```
24/// use std::path::PathBuf;
25///
26/// use rust_code_analysis::{dump_root, metrics, CppParser, ParserTrait};
27///
28/// let source_code = "int a = 42;";
29///
30/// // The path to a dummy file used to contain the source code
31/// let path = PathBuf::from("foo.c");
32/// let source_as_vec = source_code.as_bytes().to_vec();
33///
34/// // The parser of the code, in this case a CPP parser
35/// let parser = CppParser::new(source_as_vec, &path, None);
36///
37/// // Compute metrics
38/// let space = metrics(&parser, &path).unwrap();
39///
40/// // Dump all metrics
41/// dump_root(&space).unwrap();
42/// ```
43///
44/// [`Result`]: #variant.Result
45pub fn dump_root(space: &FuncSpace) -> std::io::Result<()> {
46    let stdout = StandardStream::stdout(ColorChoice::Always);
47    let mut stdout = stdout.lock();
48    dump_space(space, "", true, &mut stdout)?;
49    color(&mut stdout, Color::White)?;
50
51    Ok(())
52}
53
54fn dump_space(
55    space: &FuncSpace,
56    prefix: &str,
57    last: bool,
58    stdout: &mut StandardStreamLock,
59) -> std::io::Result<()> {
60    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
61
62    color(stdout, Color::Blue)?;
63    write!(stdout, "{prefix}{pref}")?;
64
65    intense_color(stdout, Color::Yellow)?;
66    write!(stdout, "{}: ", space.kind)?;
67
68    intense_color(stdout, Color::Cyan)?;
69    write!(stdout, "{}", space.name.as_ref().map_or("", |name| name))?;
70
71    intense_color(stdout, Color::Red)?;
72    writeln!(stdout, " (@{})", space.start_line)?;
73
74    let prefix = format!("{prefix}{pref_child}");
75    dump_metrics(&space.metrics, &prefix, space.spaces.is_empty(), stdout)?;
76
77    if let Some((last, spaces)) = space.spaces.split_last() {
78        for space in spaces {
79            dump_space(space, &prefix, false, stdout)?;
80        }
81        dump_space(last, &prefix, true, stdout)?;
82    }
83
84    Ok(())
85}
86
87fn dump_metrics(
88    metrics: &CodeMetrics,
89    prefix: &str,
90    last: bool,
91    stdout: &mut StandardStreamLock,
92) -> std::io::Result<()> {
93    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
94
95    color(stdout, Color::Blue)?;
96    write!(stdout, "{prefix}{pref}")?;
97
98    intense_color(stdout, Color::Yellow)?;
99    writeln!(stdout, "metrics")?;
100
101    let prefix = format!("{prefix}{pref_child}");
102    dump_cognitive(&metrics.cognitive, &prefix, false, stdout)?;
103    dump_cyclomatic(&metrics.cyclomatic, &prefix, false, stdout)?;
104    dump_nargs(&metrics.nargs, &prefix, false, stdout)?;
105    dump_nexits(&metrics.nexits, &prefix, false, stdout)?;
106    dump_halstead(&metrics.halstead, &prefix, false, stdout)?;
107    dump_loc(&metrics.loc, &prefix, false, stdout)?;
108    dump_nom(&metrics.nom, &prefix, false, stdout)?;
109    dump_mi(&metrics.mi, &prefix, true, stdout)
110}
111
112fn dump_cognitive(
113    stats: &cognitive::Stats,
114    prefix: &str,
115    last: bool,
116    stdout: &mut StandardStreamLock,
117) -> std::io::Result<()> {
118    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
119
120    color(stdout, Color::Blue)?;
121    write!(stdout, "{prefix}{pref}")?;
122
123    intense_color(stdout, Color::Green)?;
124    writeln!(stdout, "cognitive")?;
125
126    let prefix = format!("{prefix}{pref_child}");
127
128    dump_value("sum", stats.cognitive(), &prefix, false, stdout)?;
129    dump_value("average", stats.cognitive_average(), &prefix, true, stdout)
130}
131
132fn dump_cyclomatic(
133    stats: &cyclomatic::Stats,
134    prefix: &str,
135    last: bool,
136    stdout: &mut StandardStreamLock,
137) -> std::io::Result<()> {
138    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
139
140    color(stdout, Color::Blue)?;
141    write!(stdout, "{prefix}{pref}")?;
142
143    intense_color(stdout, Color::Green)?;
144    writeln!(stdout, "cyclomatic")?;
145
146    let prefix = format!("{prefix}{pref_child}");
147
148    dump_value("sum", stats.cyclomatic(), &prefix, false, stdout)?;
149    dump_value("average", stats.cyclomatic_average(), &prefix, true, stdout)
150}
151
152fn dump_halstead(
153    stats: &halstead::Stats,
154    prefix: &str,
155    last: bool,
156    stdout: &mut StandardStreamLock,
157) -> std::io::Result<()> {
158    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
159
160    color(stdout, Color::Blue)?;
161    write!(stdout, "{prefix}{pref}")?;
162
163    intense_color(stdout, Color::Green)?;
164    writeln!(stdout, "halstead")?;
165
166    let prefix = format!("{prefix}{pref_child}");
167
168    dump_value("n1", stats.u_operators(), &prefix, false, stdout)?;
169    dump_value("N1", stats.operators(), &prefix, false, stdout)?;
170    dump_value("n2", stats.u_operands(), &prefix, false, stdout)?;
171    dump_value("N2", stats.operands(), &prefix, false, stdout)?;
172
173    dump_value("length", stats.length(), &prefix, false, stdout)?;
174    dump_value(
175        "estimated program length",
176        stats.estimated_program_length(),
177        &prefix,
178        false,
179        stdout,
180    )?;
181    dump_value("purity ratio", stats.purity_ratio(), &prefix, false, stdout)?;
182    dump_value("vocabulary", stats.vocabulary(), &prefix, false, stdout)?;
183    dump_value("volume", stats.volume(), &prefix, false, stdout)?;
184    dump_value("difficulty", stats.difficulty(), &prefix, false, stdout)?;
185    dump_value("level", stats.level(), &prefix, false, stdout)?;
186    dump_value("effort", stats.effort(), &prefix, false, stdout)?;
187    dump_value("time", stats.time(), &prefix, false, stdout)?;
188    dump_value("bugs", stats.bugs(), &prefix, true, stdout)
189}
190
191fn dump_loc(
192    stats: &loc::Stats,
193    prefix: &str,
194    last: bool,
195    stdout: &mut StandardStreamLock,
196) -> std::io::Result<()> {
197    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
198
199    color(stdout, Color::Blue)?;
200    write!(stdout, "{prefix}{pref}")?;
201
202    intense_color(stdout, Color::Green)?;
203    writeln!(stdout, "loc")?;
204
205    let prefix = format!("{prefix}{pref_child}");
206    dump_value("sloc", stats.sloc(), &prefix, false, stdout)?;
207    dump_value("ploc", stats.ploc(), &prefix, false, stdout)?;
208    dump_value("lloc", stats.lloc(), &prefix, false, stdout)?;
209    dump_value("cloc", stats.cloc(), &prefix, false, stdout)?;
210    dump_value("blank", stats.blank(), &prefix, true, stdout)
211}
212
213fn dump_nom(
214    stats: &nom::Stats,
215    prefix: &str,
216    last: bool,
217    stdout: &mut StandardStreamLock,
218) -> std::io::Result<()> {
219    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
220
221    color(stdout, Color::Blue)?;
222    write!(stdout, "{prefix}{pref}")?;
223
224    intense_color(stdout, Color::Green)?;
225    writeln!(stdout, "nom")?;
226
227    let prefix = format!("{prefix}{pref_child}");
228    dump_value("functions", stats.functions(), &prefix, false, stdout)?;
229    dump_value("closures", stats.closures(), &prefix, false, stdout)?;
230    dump_value("total", stats.total(), &prefix, true, stdout)
231}
232
233fn dump_mi(
234    stats: &mi::Stats,
235    prefix: &str,
236    last: bool,
237    stdout: &mut StandardStreamLock,
238) -> std::io::Result<()> {
239    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
240
241    color(stdout, Color::Blue)?;
242    write!(stdout, "{prefix}{pref}")?;
243
244    intense_color(stdout, Color::Green)?;
245    writeln!(stdout, "mi")?;
246
247    let prefix = format!("{prefix}{pref_child}");
248    dump_value("mi_original", stats.mi_original(), &prefix, false, stdout)?;
249    dump_value("mi_sei", stats.mi_sei(), &prefix, false, stdout)?;
250    dump_value(
251        "mi_visual_studio",
252        stats.mi_visual_studio(),
253        &prefix,
254        true,
255        stdout,
256    )
257}
258
259fn dump_nargs(
260    stats: &nargs::Stats,
261    prefix: &str,
262    last: bool,
263    stdout: &mut StandardStreamLock,
264) -> std::io::Result<()> {
265    let (pref_child, pref) = if last { ("   ", "`- ") } else { ("|  ", "|- ") };
266
267    color(stdout, Color::Blue)?;
268    write!(stdout, "{prefix}{pref}")?;
269
270    intense_color(stdout, Color::Green)?;
271    writeln!(stdout, "nargs")?;
272
273    let prefix = format!("{prefix}{pref_child}");
274    dump_value("functions", stats.fn_args(), &prefix, false, stdout)?;
275    dump_value("closures", stats.closure_args(), &prefix, false, stdout)?;
276    dump_value("total", stats.nargs_total(), &prefix, false, stdout)?;
277    dump_value("average", stats.nargs_average(), &prefix, true, stdout)
278}
279
280fn dump_nexits(
281    stats: &exit::Stats,
282    prefix: &str,
283    last: bool,
284    stdout: &mut StandardStreamLock,
285) -> std::io::Result<()> {
286    let pref = if last { "`- " } else { "|- " };
287
288    color(stdout, Color::Blue)?;
289    write!(stdout, "{prefix}{pref}")?;
290
291    intense_color(stdout, Color::Green)?;
292    write!(stdout, "nexits: ")?;
293
294    color(stdout, Color::White)?;
295    writeln!(stdout, "{}", stats.exit())
296}
297
298fn dump_value(
299    name: &str,
300    val: f64,
301    prefix: &str,
302    last: bool,
303    stdout: &mut StandardStreamLock,
304) -> std::io::Result<()> {
305    let pref = if last { "`- " } else { "|- " };
306
307    color(stdout, Color::Blue)?;
308    write!(stdout, "{prefix}{pref}")?;
309
310    intense_color(stdout, Color::Magenta)?;
311    write!(stdout, "{name}: ")?;
312
313    color(stdout, Color::White)?;
314    writeln!(stdout, "{val}")
315}