1use std::collections::HashSet;
2use std::path::Path;
3
4use serde::Deserialize;
5
6#[derive(Debug, Default, Deserialize)]
8pub struct Config {
9 #[serde(default)]
11 pub disabled_rules: Vec<String>,
12
13 #[serde(default)]
15 pub project_type: Option<String>,
16
17 #[serde(default)]
19 pub thresholds: Thresholds,
20}
21
22#[derive(Debug, Deserialize)]
23pub struct Thresholds {
24 #[serde(default = "default_file_warn")]
26 pub file_lines_warn: usize,
27 #[serde(default = "default_file_error")]
28 pub file_lines_error: usize,
29
30 #[serde(default = "default_fn_warn")]
32 pub function_lines_warn: usize,
33 #[serde(default = "default_fn_error")]
34 pub function_lines_error: usize,
35
36 #[serde(default = "default_claude_md_max")]
38 pub claude_md_max_lines: usize,
39}
40
41fn default_file_warn() -> usize { 300 }
42fn default_file_error() -> usize { 500 }
43fn default_fn_warn() -> usize { 50 }
44fn default_fn_error() -> usize { 80 }
45fn default_claude_md_max() -> usize { 200 }
46
47impl Default for Thresholds {
48 fn default() -> Self {
49 Self {
50 file_lines_warn: 300,
51 file_lines_error: 500,
52 function_lines_warn: 50,
53 function_lines_error: 80,
54 claude_md_max_lines: 200,
55 }
56 }
57}
58
59impl Config {
60 pub fn load(root: &Path) -> Self {
63 let path = root.join(".claude-native.yml");
64 if !path.exists() {
65 return Self::default();
66 }
67 match std::fs::read_to_string(&path) {
68 Ok(content) => serde_yaml::from_str(&content).unwrap_or_default(),
69 Err(_) => Self::default(),
70 }
71 }
72
73 pub fn is_rule_disabled(&self, rule_id: &str) -> bool {
74 self.disabled_rules.iter().any(|r| r == rule_id)
75 }
76
77 pub fn disabled_set(&self) -> HashSet<String> {
78 self.disabled_rules.iter().cloned().collect()
79 }
80}