agentroot_core/index/ast_chunker/
language.rs

1//! Language detection from file paths
2
3use std::path::Path;
4
5/// Supported programming languages for AST chunking
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7pub enum Language {
8    Rust,
9    Python,
10    JavaScript,
11    TypeScript,
12    TypeScriptTsx,
13    Go,
14}
15
16impl Language {
17    pub fn as_str(&self) -> &'static str {
18        match self {
19            Self::Rust => "rust",
20            Self::Python => "python",
21            Self::JavaScript => "javascript",
22            Self::TypeScript => "typescript",
23            Self::TypeScriptTsx => "tsx",
24            Self::Go => "go",
25        }
26    }
27
28    /// Detect language from file path extension
29    pub fn from_path(path: &Path) -> Option<Self> {
30        let ext = path.extension()?.to_str()?;
31        Self::from_extension(ext)
32    }
33
34    /// Detect language from file extension string
35    pub fn from_extension(ext: &str) -> Option<Self> {
36        match ext.to_lowercase().as_str() {
37            "rs" => Some(Self::Rust),
38            "py" | "pyi" => Some(Self::Python),
39            "js" | "mjs" | "cjs" | "jsx" => Some(Self::JavaScript),
40            "ts" | "mts" | "cts" => Some(Self::TypeScript),
41            "tsx" => Some(Self::TypeScriptTsx),
42            "go" => Some(Self::Go),
43            _ => None,
44        }
45    }
46}
47
48/// Check if a file path is supported for AST chunking
49pub fn is_supported(path: &Path) -> bool {
50    Language::from_path(path).is_some()
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56
57    #[test]
58    fn test_rust_detection() {
59        assert_eq!(
60            Language::from_path(Path::new("foo.rs")),
61            Some(Language::Rust)
62        );
63        assert_eq!(
64            Language::from_path(Path::new("src/lib.rs")),
65            Some(Language::Rust)
66        );
67    }
68
69    #[test]
70    fn test_python_detection() {
71        assert_eq!(
72            Language::from_path(Path::new("foo.py")),
73            Some(Language::Python)
74        );
75        assert_eq!(
76            Language::from_path(Path::new("foo.pyi")),
77            Some(Language::Python)
78        );
79    }
80
81    #[test]
82    fn test_javascript_detection() {
83        assert_eq!(
84            Language::from_path(Path::new("foo.js")),
85            Some(Language::JavaScript)
86        );
87        assert_eq!(
88            Language::from_path(Path::new("foo.mjs")),
89            Some(Language::JavaScript)
90        );
91        assert_eq!(
92            Language::from_path(Path::new("foo.jsx")),
93            Some(Language::JavaScript)
94        );
95    }
96
97    #[test]
98    fn test_typescript_detection() {
99        assert_eq!(
100            Language::from_path(Path::new("foo.ts")),
101            Some(Language::TypeScript)
102        );
103        assert_eq!(
104            Language::from_path(Path::new("foo.tsx")),
105            Some(Language::TypeScriptTsx)
106        );
107    }
108
109    #[test]
110    fn test_go_detection() {
111        assert_eq!(Language::from_path(Path::new("foo.go")), Some(Language::Go));
112    }
113
114    #[test]
115    fn test_unsupported() {
116        assert_eq!(Language::from_path(Path::new("foo.md")), None);
117        assert_eq!(Language::from_path(Path::new("foo.txt")), None);
118        assert_eq!(Language::from_path(Path::new("foo")), None);
119    }
120
121    #[test]
122    fn test_is_supported() {
123        assert!(is_supported(Path::new("foo.rs")));
124        assert!(is_supported(Path::new("foo.py")));
125        assert!(!is_supported(Path::new("foo.md")));
126    }
127}