Skip to main content

code_analyze_core/
lang.rs

1//! Language detection by file extension.
2//!
3//! Maps file extensions to supported language identifiers.
4
5const EXTENSION_MAP: &[(&str, &str)] = &[
6    #[cfg(feature = "lang-fortran")]
7    ("f", "fortran"),
8    #[cfg(feature = "lang-fortran")]
9    ("f03", "fortran"),
10    #[cfg(feature = "lang-fortran")]
11    ("f08", "fortran"),
12    #[cfg(feature = "lang-fortran")]
13    ("f77", "fortran"),
14    #[cfg(feature = "lang-fortran")]
15    ("f90", "fortran"),
16    #[cfg(feature = "lang-fortran")]
17    ("f95", "fortran"),
18    #[cfg(feature = "lang-fortran")]
19    ("for", "fortran"),
20    #[cfg(feature = "lang-fortran")]
21    ("ftn", "fortran"),
22    #[cfg(feature = "lang-go")]
23    ("go", "go"),
24    #[cfg(feature = "lang-java")]
25    ("java", "java"),
26    #[cfg(feature = "lang-python")]
27    ("py", "python"),
28    #[cfg(feature = "lang-rust")]
29    ("rs", "rust"),
30    #[cfg(feature = "lang-typescript")]
31    ("ts", "typescript"),
32    #[cfg(feature = "lang-tsx")]
33    ("tsx", "tsx"),
34];
35
36/// Returns the language identifier for the given file extension, or `None` if unsupported.
37///
38/// The lookup is case-insensitive. Supported extensions include `rs`, `py`, `go`, `java`,
39/// `ts`, `tsx`, `f90`, `f95`, `for`, `ftn`, and other Fortran variants.
40#[must_use]
41pub fn language_for_extension(ext: &str) -> Option<&'static str> {
42    EXTENSION_MAP
43        .iter()
44        .find(|(e, _)| e.eq_ignore_ascii_case(ext))
45        .map(|(_, lang)| *lang)
46}
47
48/// Returns a static slice of all supported language names based on compiled features.
49///
50/// The returned slice contains language identifiers like `"rust"`, `"python"`, `"go"`, etc.,
51/// depending on which language features are enabled at compile time.
52#[must_use]
53pub fn supported_languages() -> &'static [&'static str] {
54    &[
55        #[cfg(feature = "lang-rust")]
56        "rust",
57        #[cfg(feature = "lang-go")]
58        "go",
59        #[cfg(feature = "lang-java")]
60        "java",
61        #[cfg(feature = "lang-python")]
62        "python",
63        #[cfg(feature = "lang-typescript")]
64        "typescript",
65        #[cfg(feature = "lang-tsx")]
66        "tsx",
67        #[cfg(feature = "lang-fortran")]
68        "fortran",
69    ]
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75
76    #[test]
77    fn test_language_for_extension_happy_path() {
78        #[cfg(feature = "lang-rust")]
79        assert_eq!(language_for_extension("rs"), Some("rust"));
80        #[cfg(feature = "lang-python")]
81        assert_eq!(language_for_extension("py"), Some("python"));
82        #[cfg(feature = "lang-go")]
83        assert_eq!(language_for_extension("go"), Some("go"));
84        #[cfg(feature = "lang-java")]
85        assert_eq!(language_for_extension("java"), Some("java"));
86        #[cfg(feature = "lang-typescript")]
87        assert_eq!(language_for_extension("ts"), Some("typescript"));
88        #[cfg(feature = "lang-tsx")]
89        assert_eq!(language_for_extension("tsx"), Some("tsx"));
90        #[cfg(feature = "lang-fortran")]
91        assert_eq!(language_for_extension("f90"), Some("fortran"));
92        #[cfg(feature = "lang-fortran")]
93        assert_eq!(language_for_extension("for"), Some("fortran"));
94        #[cfg(feature = "lang-fortran")]
95        assert_eq!(language_for_extension("ftn"), Some("fortran"));
96    }
97
98    #[test]
99    fn test_language_for_extension_edge_case() {
100        assert_eq!(language_for_extension("unknown"), None);
101        assert_eq!(language_for_extension(""), None);
102        #[cfg(feature = "lang-rust")]
103        assert_eq!(language_for_extension("RS"), Some("rust"));
104        // Uppercase Fortran extensions resolved via eq_ignore_ascii_case
105        #[cfg(feature = "lang-fortran")]
106        assert_eq!(language_for_extension("F90"), Some("fortran"));
107        #[cfg(feature = "lang-fortran")]
108        assert_eq!(language_for_extension("FOR"), Some("fortran"));
109    }
110}