impl Default for CfgBuilder {
fn default() -> Self {
Self::new()
}
}
fn write_box_line(out: &mut String, content: &str, inner: usize) {
out.push('║');
out.push_str(content);
for _ in 0..inner.saturating_sub(content.len()) {
out.push(' ');
}
out.push_str("║\n");
}
fn write_hrule(out: &mut String, left: char, fill: char, right: &str, inner: usize) {
out.push(left);
for _ in 0..inner {
out.push(fill);
}
out.push_str(right);
out.push('\n');
}
pub fn render_cfg_ascii(
cfg: &ControlFlowGraph,
metrics: &ComplexityMetrics,
width: usize,
) -> String {
let mut out = String::new();
let inner = width - 2;
write_hrule(&mut out, '╔', '═', "╗", inner);
let title = "CONTROL FLOW GRAPH";
let padding = (inner.saturating_sub(title.len())) / 2;
let mut title_line = String::new();
for _ in 0..padding {
title_line.push(' ');
}
title_line.push_str(title);
for _ in 0..(inner - padding - title.len()) {
title_line.push(' ');
}
write_box_line(&mut out, &title_line, inner);
write_hrule(&mut out, '╠', '═', "╣", inner);
let entry_lines = [
" ┌─────────┐",
" │ ENTRY │",
" └────┬────┘",
" │",
];
for line in &entry_lines {
write_box_line(&mut out, line, inner);
}
if metrics.decision_points > 0 {
let cond_lines = [
" ┌────▼────┐",
" │ if cond │",
" └────┬────┘",
" ┌────────┼────────┐",
" │ TRUE │ FALSE │",
" └────────┼────────┘",
" │",
];
for line in &cond_lines {
write_box_line(&mut out, line, inner);
}
}
let exit_lines = [
" ┌───▼────┐",
" │ EXIT │",
" └────────┘",
];
for line in &exit_lines {
write_box_line(&mut out, line, inner);
}
write_hrule(&mut out, '╠', '═', "╣", inner);
let metrics_line = format!(
" Nodes: {} │ Edges: {} │ Cyclomatic: {} │ Essential: {} │ Max Depth: {}",
cfg.node_count(),
cfg.edge_count(),
metrics.cyclomatic,
metrics.essential,
metrics.max_depth
);
let truncated = if metrics_line.len() > inner {
&metrics_line[..inner]
} else {
&metrics_line
};
write_box_line(&mut out, truncated, inner);
write_hrule(&mut out, '╚', '═', "╝", inner);
out
}
#[cfg(test)]
#[path = "cfg_tests_ml_015.rs"]
mod tests_extracted;