agentic_codebase/index/
language_index.rs1use std::collections::HashMap;
7
8use crate::graph::CodeGraph;
9use crate::types::Language;
10
11#[derive(Debug, Clone, Default)]
13pub struct LanguageIndex {
14 by_language: HashMap<Language, Vec<u64>>,
15}
16
17impl LanguageIndex {
18 pub fn build(graph: &CodeGraph) -> Self {
20 let mut by_language: HashMap<Language, Vec<u64>> = HashMap::new();
21
22 for unit in graph.units() {
23 by_language.entry(unit.language).or_default().push(unit.id);
24 }
25
26 Self { by_language }
27 }
28
29 pub fn lookup(&self, language: Language) -> &[u64] {
33 self.by_language
34 .get(&language)
35 .map(|v| v.as_slice())
36 .unwrap_or(&[])
37 }
38
39 pub fn count(&self, language: Language) -> usize {
41 self.by_language
42 .get(&language)
43 .map(|v| v.len())
44 .unwrap_or(0)
45 }
46
47 pub fn languages(&self) -> Vec<Language> {
49 self.by_language.keys().copied().collect()
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56 use crate::graph::CodeGraph;
57 use crate::types::{CodeUnit, CodeUnitType, Language, Span};
58 use std::path::PathBuf;
59
60 fn make_unit(language: Language) -> CodeUnit {
61 CodeUnit::new(
62 CodeUnitType::Function,
63 language,
64 "test_fn".to_string(),
65 "mod::test_fn".to_string(),
66 PathBuf::from("src/lib.rs"),
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 = LanguageIndex::build(&graph);
75 assert_eq!(index.count(Language::Rust), 0);
76 assert_eq!(index.lookup(Language::Rust), &[] as &[u64]);
77 assert!(index.languages().is_empty());
78 }
79
80 #[test]
81 fn test_grouped_lookup() {
82 let mut graph = CodeGraph::default();
83 graph.add_unit(make_unit(Language::Rust));
84 graph.add_unit(make_unit(Language::Rust));
85 graph.add_unit(make_unit(Language::Python));
86 graph.add_unit(make_unit(Language::TypeScript));
87
88 let index = LanguageIndex::build(&graph);
89 assert_eq!(index.count(Language::Rust), 2);
90 assert_eq!(index.count(Language::Python), 1);
91 assert_eq!(index.count(Language::TypeScript), 1);
92 assert_eq!(index.count(Language::Go), 0);
93
94 assert_eq!(index.lookup(Language::Rust), &[0, 1]);
95 assert_eq!(index.lookup(Language::Python), &[2]);
96 }
97
98 #[test]
99 fn test_languages_list() {
100 let mut graph = CodeGraph::default();
101 graph.add_unit(make_unit(Language::Rust));
102 graph.add_unit(make_unit(Language::Go));
103
104 let index = LanguageIndex::build(&graph);
105 let mut langs = index.languages();
106 langs.sort_by_key(|l| *l as u8);
107 assert_eq!(langs, vec![Language::Rust, Language::Go]);
108 }
109}