agentic_codebase/index/
path_index.rs1use std::collections::HashMap;
7use std::path::{Path, PathBuf};
8
9use crate::graph::CodeGraph;
10
11#[derive(Debug, Clone, Default)]
13pub struct PathIndex {
14 by_path: HashMap<PathBuf, Vec<u64>>,
15 paths: Vec<PathBuf>,
16}
17
18impl PathIndex {
19 pub fn build(graph: &CodeGraph) -> Self {
21 let mut by_path: HashMap<PathBuf, Vec<u64>> = HashMap::new();
22
23 for unit in graph.units() {
24 by_path
25 .entry(unit.file_path.clone())
26 .or_default()
27 .push(unit.id);
28 }
29
30 let mut paths: Vec<PathBuf> = by_path.keys().cloned().collect();
31 paths.sort();
32
33 Self { by_path, paths }
34 }
35
36 pub fn lookup(&self, path: &Path) -> &[u64] {
40 self.by_path.get(path).map(|v| v.as_slice()).unwrap_or(&[])
41 }
42
43 pub fn paths(&self) -> &[PathBuf] {
45 &self.paths
46 }
47
48 pub fn file_count(&self) -> usize {
50 self.paths.len()
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57 use crate::graph::CodeGraph;
58 use crate::types::{CodeUnit, CodeUnitType, Language, Span};
59
60 fn make_unit(file_path: &str) -> CodeUnit {
61 CodeUnit::new(
62 CodeUnitType::Function,
63 Language::Rust,
64 "test_fn".to_string(),
65 "mod::test_fn".to_string(),
66 PathBuf::from(file_path),
67 Span::new(1, 0, 10, 0),
68 )
69 }
70
71 #[test]
72 fn test_empty_index() {
73 let graph = CodeGraph::default();
74 let index = PathIndex::build(&graph);
75 assert_eq!(index.file_count(), 0);
76 assert!(index.paths().is_empty());
77 assert_eq!(index.lookup(Path::new("src/lib.rs")), &[] as &[u64]);
78 }
79
80 #[test]
81 fn test_path_lookup() {
82 let mut graph = CodeGraph::default();
83 graph.add_unit(make_unit("src/lib.rs"));
84 graph.add_unit(make_unit("src/lib.rs"));
85 graph.add_unit(make_unit("src/main.rs"));
86
87 let index = PathIndex::build(&graph);
88 assert_eq!(index.file_count(), 2);
89 assert_eq!(index.lookup(Path::new("src/lib.rs")), &[0, 1]);
90 assert_eq!(index.lookup(Path::new("src/main.rs")), &[2]);
91 assert_eq!(index.lookup(Path::new("src/other.rs")), &[] as &[u64]);
92 }
93
94 #[test]
95 fn test_paths_sorted() {
96 let mut graph = CodeGraph::default();
97 graph.add_unit(make_unit("src/z_file.rs"));
98 graph.add_unit(make_unit("src/a_file.rs"));
99 graph.add_unit(make_unit("src/m_file.rs"));
100
101 let index = PathIndex::build(&graph);
102 let paths = index.paths();
103 assert_eq!(paths.len(), 3);
104 assert_eq!(paths[0], PathBuf::from("src/a_file.rs"));
105 assert_eq!(paths[1], PathBuf::from("src/m_file.rs"));
106 assert_eq!(paths[2], PathBuf::from("src/z_file.rs"));
107 }
108}