Skip to main content

blast_radius/report/
mod.rs

1use anyhow::Result;
2
3use crate::cli::OutputFormat;
4use crate::graph::{AnalysisMode, AnalysisResult};
5
6mod graph_formats;
7use graph_formats::{render_dot, render_mermaid};
8
9mod theme;
10
11mod tree;
12use tree::render_tree;
13
14pub fn render(
15    format: &OutputFormat,
16    result: &AnalysisResult,
17    verbose: bool,
18    color: bool,
19) -> Result<String> {
20    let rendered = match format {
21        // The risk-verdict tree is meaningless for a whole-repo graph dump, so
22        // fall back to a plain importer-direction edge listing.
23        OutputFormat::Tree if matches!(result.mode, AnalysisMode::Graph) => {
24            render_graph_edge_list(result)
25        }
26        OutputFormat::Tree => render_tree(result, verbose, color),
27        OutputFormat::Json => serde_json::to_string_pretty(result)?,
28        OutputFormat::Mermaid => render_mermaid(result),
29        OutputFormat::Dot => render_dot(result),
30    };
31
32    Ok(rendered)
33}
34
35/// A plain `importer -> importee` listing for `graph` in the default (tree)
36/// format. Edges are stored depended-upon -> consumer, so flip for display.
37fn render_graph_edge_list(result: &AnalysisResult) -> String {
38    use std::collections::BTreeMap;
39
40    let labels: BTreeMap<&str, &str> = result
41        .nodes
42        .iter()
43        .map(|node| (node.id.as_str(), node.label.as_str()))
44        .collect();
45    let mut lines: Vec<String> = result
46        .edges
47        .iter()
48        .map(|edge| {
49            let importer = labels.get(edge.to.as_str()).copied().unwrap_or(&edge.to);
50            let importee = labels
51                .get(edge.from.as_str())
52                .copied()
53                .unwrap_or(&edge.from);
54            format!("{importer} -> {importee}")
55        })
56        .collect();
57    lines.sort();
58    if lines.is_empty() {
59        format!("{} files, no import edges", result.source_file_count)
60    } else {
61        lines.join("\n")
62    }
63}