code_split_core/
builder.rs1use crate::graph::{Edge, EdgeKind, Graph, Node, NodeId, NodeKind};
2use std::collections::HashSet;
3
4#[derive(Debug, Default)]
5pub struct GraphBuilder {
6 graph: Graph,
7 seen_nodes: HashSet<NodeId>,
8}
9
10impl GraphBuilder {
11 pub fn new() -> Self {
12 Self::default()
13 }
14
15 pub fn add_node(&mut self, node: Node) -> bool {
16 if self.seen_nodes.insert(node.id.clone()) {
17 self.graph.nodes.push(node);
18 true
19 } else {
20 false
21 }
22 }
23
24 pub fn add_edge(&mut self, edge: Edge) {
25 self.graph.edges.push(edge);
26 }
27
28 pub fn node_count(&self) -> usize {
29 self.graph.nodes.len()
30 }
31
32 pub fn edge_count_of_kind(&self, kind: EdgeKind) -> usize {
33 self.graph.edges.iter().filter(|e| e.kind == kind).count()
34 }
35
36 pub fn nodes(&self) -> &Vec<Node> {
37 &self.graph.nodes
38 }
39
40 pub fn nodes_mut(&mut self) -> &mut Vec<Node> {
41 &mut self.graph.nodes
42 }
43
44 pub fn find_file_node(&self, path: &str) -> Option<NodeId> {
47 let mut found = None;
48 for node in &self.graph.nodes {
49 if node.kind == NodeKind::File && node.path == path {
50 if found.is_some() {
51 return None;
52 }
53 found = Some(node.id.clone());
54 }
55 }
56 found
57 }
58
59 pub fn build(self) -> Graph {
60 self.graph
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67 use crate::graph::NodeKind;
68
69 fn node(id: &str) -> Node {
70 Node {
71 id: id.into(),
72 kind: NodeKind::Crate,
73 name: id.into(),
74 path: String::new(),
75 parent: None,
76 external: None,
77 version: None,
78 visibility: None,
79 loc: None,
80 line: None,
81 item_count: None,
82 method_count: None,
83 complexity: None,
84 cycle_kind: None,
85 }
86 }
87
88 #[test]
89 fn add_node_deduplicates_by_id() {
90 let mut b = GraphBuilder::new();
91 assert!(b.add_node(node("x")));
92 assert!(!b.add_node(node("x")));
93 let g = b.build();
94 assert_eq!(g.nodes.len(), 1);
95 }
96}