agentic_codebase/graph/builder.rs
1//! Fluent API for building code graphs.
2//!
3//! The `GraphBuilder` provides a convenient way to construct graphs
4//! by chaining method calls.
5
6use crate::types::{AcbResult, CodeUnit, Edge};
7
8use super::code_graph::CodeGraph;
9
10/// Fluent builder for constructing a [`CodeGraph`].
11///
12/// # Examples
13///
14/// ```
15/// use agentic_codebase::graph::GraphBuilder;
16/// use agentic_codebase::types::*;
17/// use std::path::PathBuf;
18///
19/// let graph = GraphBuilder::new(256)
20/// .add_unit(CodeUnit::new(
21/// CodeUnitType::Module,
22/// Language::Python,
23/// "mymodule".into(),
24/// "mymodule".into(),
25/// PathBuf::from("mymodule.py"),
26/// Span::new(1, 0, 100, 0),
27/// ))
28/// .add_unit(CodeUnit::new(
29/// CodeUnitType::Function,
30/// Language::Python,
31/// "my_func".into(),
32/// "mymodule.my_func".into(),
33/// PathBuf::from("mymodule.py"),
34/// Span::new(10, 0, 20, 0),
35/// ))
36/// .add_edge(Edge::new(0, 1, EdgeType::Contains))
37/// .build()
38/// .unwrap();
39/// ```
40pub struct GraphBuilder {
41 graph: CodeGraph,
42 pending_edges: Vec<Edge>,
43 errors: Vec<String>,
44}
45
46impl GraphBuilder {
47 /// Create a new builder with the given feature vector dimension.
48 pub fn new(dimension: usize) -> Self {
49 Self {
50 graph: CodeGraph::new(dimension),
51 pending_edges: Vec::new(),
52 errors: Vec::new(),
53 }
54 }
55
56 /// Create with default dimension (256).
57 pub fn with_default_dimension() -> Self {
58 Self::new(crate::types::DEFAULT_DIMENSION)
59 }
60
61 /// Add a code unit to the graph.
62 pub fn add_unit(mut self, unit: CodeUnit) -> Self {
63 self.graph.add_unit(unit);
64 self
65 }
66
67 /// Add an edge (deferred until build).
68 pub fn add_edge(mut self, edge: Edge) -> Self {
69 self.pending_edges.push(edge);
70 self
71 }
72
73 /// Consume the builder and produce a [`CodeGraph`].
74 ///
75 /// All pending edges are validated and added. Returns an error if
76 /// any edge is invalid.
77 pub fn build(mut self) -> AcbResult<CodeGraph> {
78 for edge in self.pending_edges {
79 self.graph.add_edge(edge)?;
80 }
81 Ok(self.graph)
82 }
83
84 /// Build, ignoring invalid edges (logs warnings).
85 pub fn build_lenient(mut self) -> CodeGraph {
86 for edge in self.pending_edges {
87 if let Err(e) = self.graph.add_edge(edge) {
88 tracing::warn!("Skipping invalid edge: {}", e);
89 self.errors.push(format!("{}", e));
90 }
91 }
92 self.graph
93 }
94
95 /// Returns any errors accumulated during lenient build.
96 pub fn errors(&self) -> &[String] {
97 &self.errors
98 }
99}