Skip to main content

agentic_codebase/types/
language.rs

1//! Programming language detection and enumeration.
2
3use serde::{Deserialize, Serialize};
4use std::path::Path;
5
6/// Supported programming languages.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
8#[repr(u8)]
9pub enum Language {
10    /// Python (.py, .pyi)
11    Python = 0,
12    /// Rust (.rs)
13    Rust = 1,
14    /// TypeScript (.ts, .tsx)
15    TypeScript = 2,
16    /// JavaScript (.js, .jsx, .mjs, .cjs)
17    JavaScript = 3,
18    /// Go (.go)
19    Go = 4,
20    /// C++ (.cpp, .cc, .cxx, .h, .hpp, .hxx)
21    Cpp = 5,
22    /// Java (.java)
23    Java = 6,
24    /// C# (.cs)
25    CSharp = 7,
26    /// Unknown or unsupported language
27    Unknown = 255,
28}
29
30impl Language {
31    /// Convert from raw byte value.
32    pub fn from_u8(value: u8) -> Option<Self> {
33        match value {
34            0 => Some(Self::Python),
35            1 => Some(Self::Rust),
36            2 => Some(Self::TypeScript),
37            3 => Some(Self::JavaScript),
38            4 => Some(Self::Go),
39            5 => Some(Self::Cpp),
40            6 => Some(Self::Java),
41            7 => Some(Self::CSharp),
42            255 => Some(Self::Unknown),
43            _ => None,
44        }
45    }
46
47    /// Detect language from file extension.
48    pub fn from_extension(ext: &str) -> Self {
49        match ext.to_lowercase().as_str() {
50            "py" | "pyi" => Self::Python,
51            "rs" => Self::Rust,
52            "ts" | "tsx" => Self::TypeScript,
53            "js" | "jsx" | "mjs" | "cjs" => Self::JavaScript,
54            "go" => Self::Go,
55            "cpp" | "cc" | "cxx" | "c++" | "h" | "hpp" | "hxx" | "hh" => Self::Cpp,
56            "java" => Self::Java,
57            "cs" => Self::CSharp,
58            _ => Self::Unknown,
59        }
60    }
61
62    /// Detect language from file path.
63    pub fn from_path(path: &Path) -> Self {
64        path.extension()
65            .and_then(|ext| ext.to_str())
66            .map(Self::from_extension)
67            .unwrap_or(Self::Unknown)
68    }
69
70    /// Returns the tree-sitter language for this enum variant.
71    pub fn tree_sitter_language(&self) -> Option<tree_sitter::Language> {
72        match self {
73            Self::Python => Some(tree_sitter_python::language()),
74            Self::Rust => Some(tree_sitter_rust::language()),
75            Self::TypeScript => Some(tree_sitter_typescript::language_typescript()),
76            Self::JavaScript => Some(tree_sitter_javascript::language()),
77            Self::Go => Some(tree_sitter_go::language()),
78            Self::Cpp => Some(tree_sitter_cpp::language()),
79            Self::Java => Some(tree_sitter_java::language()),
80            Self::CSharp => Some(tree_sitter_c_sharp::language()),
81            Self::Unknown => None,
82        }
83    }
84
85    /// Returns a human-readable name for the language.
86    pub fn name(&self) -> &'static str {
87        match self {
88            Self::Python => "Python",
89            Self::Rust => "Rust",
90            Self::TypeScript => "TypeScript",
91            Self::JavaScript => "JavaScript",
92            Self::Go => "Go",
93            Self::Cpp => "C++",
94            Self::Java => "Java",
95            Self::CSharp => "C#",
96            Self::Unknown => "Unknown",
97        }
98    }
99}
100
101impl std::fmt::Display for Language {
102    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
103        write!(f, "{}", self.name())
104    }
105}