use crate::core::call_graph::CallGraph;
use crate::core::graph_index;
pub fn handle(symbol: &str, file: Option<&str>, project_root: &str) -> String {
let index = graph_index::load_or_build(project_root);
let graph = CallGraph::load_or_build(project_root, &index);
let _ = graph.save();
let mut callers = graph.callers_of(symbol);
if let Some(f) = file {
callers.retain(|e| e.caller_file.contains(f));
}
if callers.is_empty() {
return format!(
"No callers found for '{}' ({} edges in graph)",
symbol,
graph.edges.len()
);
}
let mut out = format!("{} caller(s) of '{symbol}':\n", callers.len());
for edge in &callers {
out.push_str(&format!(
" {} → {} (L{})\n",
edge.caller_file, edge.caller_symbol, edge.caller_line
));
}
out
}
#[cfg(test)]
mod tests {
use crate::core::call_graph::{CallEdge, CallGraph};
#[test]
fn format_callers_output() {
let mut graph = CallGraph::new("/tmp");
graph.edges.push(CallEdge {
caller_file: "src/main.rs".to_string(),
caller_symbol: "main".to_string(),
caller_line: 5,
callee_name: "init".to_string(),
});
let callers = graph.callers_of("init");
assert_eq!(callers.len(), 1);
assert_eq!(callers[0].caller_symbol, "main");
}
}