Skip to main content

icb_graph/
visualizer.rs

1use crate::graph::{CodePropertyGraph, Edge};
2use icb_common::NodeKind;
3use petgraph::visit::{EdgeRef, IntoEdgeReferences};
4use std::fmt::Write;
5
6/// Export the call graph to Graphviz DOT format.
7///
8/// Only function/class nodes and call edges are included.
9pub fn export_call_dot(cpg: &CodePropertyGraph) -> String {
10    let mut s = String::new();
11    writeln!(s, "digraph CallGraph {{").unwrap();
12    writeln!(s, "  rankdir=LR;").unwrap();
13    writeln!(s, "  node [shape=box, style=rounded];").unwrap();
14
15    for node_idx in cpg.graph.node_indices() {
16        let node = &cpg.graph[node_idx];
17        match node.kind {
18            NodeKind::Function | NodeKind::Class => {
19                let label = node.name.as_deref().unwrap_or("?");
20                writeln!(
21                    s,
22                    "  n{} [label=\"{}\\nline {}\"];",
23                    node_idx.index(),
24                    label,
25                    node.start_line
26                )
27                .unwrap();
28            }
29            _ => {}
30        }
31    }
32
33    for edge_ref in cpg.graph.edge_references() {
34        if *edge_ref.weight() == Edge::Call {
35            writeln!(
36                s,
37                "  n{} -> n{};",
38                edge_ref.source().index(),
39                edge_ref.target().index()
40            )
41            .unwrap();
42        }
43    }
44
45    writeln!(s, "}}").unwrap();
46    s
47}