smelt_validator/
config.rs1use crate::error::ValidationResult;
4use serde::{Deserialize, Serialize};
5use std::path::Path;
6
7#[derive(Debug, Clone, Default, Serialize, Deserialize)]
9pub struct ValidationConfig {
10 #[serde(default)]
12 pub architecture: ArchitectureConfig,
13
14 #[serde(default)]
16 pub semantic: SemanticConfig,
17
18 #[serde(default)]
20 pub intent: IntentConfig,
21}
22
23#[derive(Debug, Clone, Default, Serialize, Deserialize)]
25pub struct ArchitectureConfig {
26 #[serde(default)]
28 pub layers: Vec<Layer>,
29
30 #[serde(default = "default_true")]
32 pub check_circular_deps: bool,
33
34 #[serde(default = "default_true")]
36 pub enforce_layers: bool,
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct Layer {
42 pub name: String,
44
45 pub paths: Vec<String>,
47
48 #[serde(default)]
50 pub can_depend_on: Vec<String>,
51
52 #[serde(default)]
54 pub prohibited_dependencies: Vec<String>,
55}
56
57#[derive(Debug, Clone, Serialize, Deserialize)]
59pub struct SemanticConfig {
60 #[serde(default = "default_true")]
62 pub check_breaking_changes: bool,
63
64 #[serde(default = "default_true")]
66 pub breaking_changes_error: bool,
67
68 #[serde(default = "default_true")]
70 pub check_visibility: bool,
71
72 #[serde(default)]
74 pub review_new_public_api: bool,
75
76 #[serde(default)]
78 pub complexity: ComplexityConfig,
79}
80
81impl Default for SemanticConfig {
82 fn default() -> Self {
83 Self {
84 check_breaking_changes: true,
85 breaking_changes_error: true,
86 check_visibility: true,
87 review_new_public_api: false,
88 complexity: ComplexityConfig::default(),
89 }
90 }
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct ComplexityConfig {
96 #[serde(default = "default_complexity")]
98 pub max_cyclomatic: u32,
99
100 #[serde(default = "default_cognitive")]
102 pub max_cognitive: u32,
103
104 #[serde(default = "default_delta")]
106 pub max_complexity_increase: i32,
107
108 #[serde(default)]
110 pub complexity_error: bool,
111}
112
113impl Default for ComplexityConfig {
114 fn default() -> Self {
115 Self {
116 max_cyclomatic: 15,
117 max_cognitive: 25,
118 max_complexity_increase: 10,
119 complexity_error: false,
120 }
121 }
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize)]
126pub struct IntentConfig {
127 #[serde(default = "default_true")]
129 pub validate_scope: bool,
130
131 #[serde(default)]
133 pub require_rationale_for_large_changes: bool,
134
135 #[serde(default = "default_large_threshold")]
137 pub large_change_threshold: usize,
138}
139
140impl Default for IntentConfig {
141 fn default() -> Self {
142 Self {
143 validate_scope: true,
144 require_rationale_for_large_changes: false,
145 large_change_threshold: 10,
146 }
147 }
148}
149
150fn default_true() -> bool {
151 true
152}
153
154fn default_complexity() -> u32 {
155 15
156}
157
158fn default_cognitive() -> u32 {
159 25
160}
161
162fn default_delta() -> i32 {
163 10
164}
165
166fn default_large_threshold() -> usize {
167 10
168}
169
170impl ValidationConfig {
171 pub fn load(path: &Path) -> ValidationResult<Self> {
173 let content = std::fs::read_to_string(path)?;
174 let config: Self = serde_yaml::from_str(&content)?;
175 Ok(config)
176 }
177
178 pub fn load_or_default(smelt_dir: &Path) -> Self {
180 let crucible_path = smelt_dir.join("crucible.yaml");
182 if crucible_path.exists() {
183 if let Ok(config) = Self::load(&crucible_path) {
184 return config;
185 }
186 }
187
188 let validation_path = smelt_dir.join("validation.yaml");
190 if validation_path.exists() {
191 if let Ok(config) = Self::load(&validation_path) {
192 return config;
193 }
194 }
195
196 Self::default()
198 }
199
200 pub fn strict() -> Self {
202 Self {
203 architecture: ArchitectureConfig {
204 check_circular_deps: true,
205 enforce_layers: true,
206 layers: Vec::new(),
207 },
208 semantic: SemanticConfig {
209 check_breaking_changes: true,
210 breaking_changes_error: true,
211 check_visibility: true,
212 review_new_public_api: true,
213 complexity: ComplexityConfig {
214 max_cyclomatic: 10,
215 max_cognitive: 15,
216 max_complexity_increase: 5,
217 complexity_error: true,
218 },
219 },
220 intent: IntentConfig {
221 validate_scope: true,
222 require_rationale_for_large_changes: true,
223 large_change_threshold: 5,
224 },
225 }
226 }
227}