project_rag/relations/repomap/
mod.rs

1//! RepoMap-style code relationship extraction.
2//!
3//! This module provides AST-based extraction of symbol definitions and references
4//! for all languages supported by tree-sitter. It's the fallback provider when
5//! stack-graphs isn't available for a language.
6//!
7//! ## How it works
8//!
9//! 1. **Definition extraction**: Parse AST and extract function/class/method definitions
10//! 2. **Reference finding**: Find identifier occurrences that match known symbol names
11//!
12//! ## Accuracy
13//!
14//! This approach achieves ~70% accuracy because it uses heuristic name matching
15//! rather than full semantic analysis. It may:
16//! - Miss references to renamed imports
17//! - Include false positives for common names
18//! - Not resolve which overload is being called
19
20pub mod reference_finder;
21pub mod symbol_extractor;
22
23use std::collections::HashMap;
24
25use anyhow::Result;
26
27use crate::indexer::FileInfo;
28use crate::relations::{Definition, PrecisionLevel, Reference, RelationsProvider};
29
30pub use reference_finder::ReferenceFinder;
31pub use symbol_extractor::SymbolExtractor;
32
33/// RepoMap-style relations provider using AST-based extraction.
34pub struct RepoMapProvider {
35    /// Symbol extractor for parsing definitions
36    symbol_extractor: SymbolExtractor,
37    /// Reference finder for locating symbol usages
38    reference_finder: ReferenceFinder,
39}
40
41impl RepoMapProvider {
42    /// Create a new RepoMap provider
43    pub fn new() -> Self {
44        Self {
45            symbol_extractor: SymbolExtractor::new(),
46            reference_finder: ReferenceFinder::new(),
47        }
48    }
49}
50
51impl Default for RepoMapProvider {
52    fn default() -> Self {
53        Self::new()
54    }
55}
56
57impl RelationsProvider for RepoMapProvider {
58    fn extract_definitions(&self, file_info: &FileInfo) -> Result<Vec<Definition>> {
59        self.symbol_extractor.extract_definitions(file_info)
60    }
61
62    fn extract_references(
63        &self,
64        file_info: &FileInfo,
65        symbol_index: &HashMap<String, Vec<Definition>>,
66    ) -> Result<Vec<Reference>> {
67        self.reference_finder
68            .find_references(file_info, symbol_index)
69    }
70
71    fn supports_language(&self, _language: &str) -> bool {
72        // RepoMap supports all languages (with varying accuracy)
73        true
74    }
75
76    fn precision_level(&self, _language: &str) -> PrecisionLevel {
77        PrecisionLevel::Medium
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84
85    #[test]
86    fn test_repomap_provider_creation() {
87        let provider = RepoMapProvider::new();
88        assert!(provider.supports_language("Rust"));
89        assert!(provider.supports_language("Python"));
90        assert!(provider.supports_language("Unknown"));
91    }
92
93    #[test]
94    fn test_precision_level() {
95        let provider = RepoMapProvider::new();
96        assert_eq!(provider.precision_level("Rust"), PrecisionLevel::Medium);
97        assert_eq!(provider.precision_level("Python"), PrecisionLevel::Medium);
98    }
99}