Skip to main content

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}