arborist/types.rs
1use serde::{Deserialize, Serialize};
2use std::fmt;
3use std::str::FromStr;
4
5/// Supported programming languages.
6///
7/// Each variant corresponds to a compile-time feature flag. Languages whose
8/// feature flag is not enabled can still be named, but attempting to analyze
9/// code in that language will return [`ArboristError::LanguageNotEnabled`].
10///
11/// The enum is `#[non_exhaustive]` — new languages may be added in minor
12/// releases without breaking existing match arms.
13///
14/// [`ArboristError::LanguageNotEnabled`]: crate::ArboristError::LanguageNotEnabled
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
16#[non_exhaustive]
17pub enum Language {
18 Rust,
19 Python,
20 JavaScript,
21 TypeScript,
22 Java,
23 CSharp,
24 Cpp,
25 C,
26 Go,
27 Php,
28 Kotlin,
29 Swift,
30}
31
32impl fmt::Display for Language {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 match self {
35 Language::Rust => write!(f, "Rust"),
36 Language::Python => write!(f, "Python"),
37 Language::JavaScript => write!(f, "JavaScript"),
38 Language::TypeScript => write!(f, "TypeScript"),
39 Language::Java => write!(f, "Java"),
40 Language::CSharp => write!(f, "C#"),
41 Language::Cpp => write!(f, "C++"),
42 Language::C => write!(f, "C"),
43 Language::Go => write!(f, "Go"),
44 Language::Php => write!(f, "PHP"),
45 Language::Kotlin => write!(f, "Kotlin"),
46 Language::Swift => write!(f, "Swift"),
47 }
48 }
49}
50
51impl FromStr for Language {
52 type Err = String;
53
54 fn from_str(s: &str) -> Result<Self, Self::Err> {
55 match s.to_lowercase().as_str() {
56 "rust" => Ok(Language::Rust),
57 "python" => Ok(Language::Python),
58 "javascript" | "js" => Ok(Language::JavaScript),
59 "typescript" | "ts" => Ok(Language::TypeScript),
60 "java" => Ok(Language::Java),
61 "csharp" | "c#" => Ok(Language::CSharp),
62 "cpp" | "c++" => Ok(Language::Cpp),
63 "c" => Ok(Language::C),
64 "go" => Ok(Language::Go),
65 "php" => Ok(Language::Php),
66 "kotlin" | "kt" => Ok(Language::Kotlin),
67 "swift" => Ok(Language::Swift),
68 _ => Err(format!("Unknown language: {s}")),
69 }
70 }
71}
72
73/// Metrics for a single function or method.
74///
75/// Each function or method discovered by the AST walker produces one
76/// `FunctionMetrics` value. Closures and lambdas do not produce their own
77/// entries; they contribute to the metrics of their containing function.
78///
79/// All three complexity dimensions are always populated. The optional
80/// `exceeds_threshold` field is only set when an [`AnalysisConfig`] with a
81/// `cognitive_threshold` is used.
82#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
83pub struct FunctionMetrics {
84 /// Function or method name (e.g., `"process"` or `"MyStruct::method"`).
85 pub name: String,
86 /// 1-based start line number.
87 pub start_line: usize,
88 /// 1-based end line number.
89 pub end_line: usize,
90 /// Cognitive complexity (SonarSource algorithm).
91 pub cognitive: u64,
92 /// Cyclomatic complexity (McCabe).
93 pub cyclomatic: u64,
94 /// Source lines of code within the function.
95 pub sloc: u64,
96 /// `Some(true)` if cognitive complexity exceeds configured threshold,
97 /// `Some(false)` if within threshold, `None` if no threshold configured.
98 pub exceeds_threshold: Option<bool>,
99}
100
101/// Analysis report for a complete source file.
102///
103/// Returned by [`analyze_file`](crate::analyze_file) and
104/// [`analyze_source`](crate::analyze_source). Contains per-function metrics
105/// and file-level aggregates. Implements `Serialize` and `Deserialize` for
106/// easy JSON output.
107#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
108pub struct FileReport {
109 /// File path (empty string for in-memory analysis).
110 pub path: String,
111 /// Detected or specified language.
112 pub language: Language,
113 /// Functions found, ordered by `start_line` ascending.
114 pub functions: Vec<FunctionMetrics>,
115 /// Sum of all functions' cognitive complexity.
116 pub file_cognitive: u64,
117 /// Sum of all functions' cyclomatic complexity.
118 pub file_cyclomatic: u64,
119 /// Total source lines in the entire file (includes top-level code).
120 pub file_sloc: u64,
121}
122
123/// User-configurable analysis parameters.
124///
125/// Pass to [`analyze_file_with_config`](crate::analyze_file_with_config) or
126/// [`analyze_source_with_config`](crate::analyze_source_with_config) to
127/// control threshold flagging and method inclusion. The [`Default`] impl
128/// sets no threshold and includes methods.
129#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
130pub struct AnalysisConfig {
131 /// When set, populates `exceeds_threshold` on each `FunctionMetrics`.
132 pub cognitive_threshold: Option<u64>,
133 /// Whether to include class/struct methods (default: `true`).
134 pub include_methods: bool,
135}
136
137impl Default for AnalysisConfig {
138 fn default() -> Self {
139 Self {
140 cognitive_threshold: None,
141 include_methods: true,
142 }
143 }
144}