Skip to main content

code_baseline/cli/
toml_config.rs

1use crate::config::{RuleConfig, Severity};
2use serde::Deserialize;
3
4/// Top-level TOML config file structure.
5#[derive(Debug, Deserialize)]
6pub struct TomlConfig {
7    pub baseline: BaselineSection,
8    #[serde(default)]
9    pub rule: Vec<TomlRule>,
10}
11
12/// A `[[baseline.scoped]]` entry that applies a preset to a specific directory.
13#[derive(Debug, Clone, Deserialize)]
14pub struct ScopedPreset {
15    pub preset: String,
16    pub path: String,
17}
18
19/// The `[baseline]` section.
20#[derive(Debug, Deserialize)]
21pub struct BaselineSection {
22    #[allow(dead_code)]
23    pub name: Option<String>,
24    #[serde(default)]
25    pub include: Vec<String>,
26    #[serde(default)]
27    pub exclude: Vec<String>,
28    #[serde(default)]
29    pub extends: Vec<String>,
30    /// Paths to plugin TOML files containing additional rules
31    #[serde(default)]
32    pub plugins: Vec<String>,
33    /// Scoped presets: apply a preset only to files under a specific path
34    #[serde(default)]
35    pub scoped: Vec<ScopedPreset>,
36}
37
38/// A single `[[rule]]` entry.
39#[derive(Debug, Clone, Deserialize)]
40pub struct TomlRule {
41    pub id: String,
42    #[serde(rename = "type")]
43    pub rule_type: String,
44    #[serde(default = "default_severity")]
45    pub severity: String,
46    pub glob: Option<String>,
47    #[serde(default)]
48    pub message: String,
49    pub suggest: Option<String>,
50    #[serde(default)]
51    pub allowed_classes: Vec<String>,
52    #[serde(default)]
53    pub token_map: Vec<String>,
54    pub pattern: Option<String>,
55    pub max_count: Option<usize>,
56    #[serde(default)]
57    pub packages: Vec<String>,
58    #[serde(default)]
59    pub regex: bool,
60    pub manifest: Option<String>,
61    #[serde(default)]
62    pub exclude_glob: Vec<String>,
63    pub file_contains: Option<String>,
64    pub file_not_contains: Option<String>,
65    #[serde(default)]
66    pub required_files: Vec<String>,
67    #[serde(default)]
68    pub forbidden_files: Vec<String>,
69    pub condition_pattern: Option<String>,
70}
71
72fn default_severity() -> String {
73    "warning".into()
74}
75
76impl Default for TomlRule {
77    fn default() -> Self {
78        Self {
79            id: String::new(),
80            rule_type: String::new(),
81            severity: default_severity(),
82            glob: None,
83            message: String::new(),
84            suggest: None,
85            allowed_classes: Vec::new(),
86            token_map: Vec::new(),
87            pattern: None,
88            max_count: None,
89            packages: Vec::new(),
90            regex: false,
91            manifest: None,
92            exclude_glob: Vec::new(),
93            file_contains: None,
94            file_not_contains: None,
95            required_files: Vec::new(),
96            forbidden_files: Vec::new(),
97            condition_pattern: None,
98        }
99    }
100}
101
102impl TomlRule {
103    /// Convert to the core `RuleConfig` type.
104    pub fn to_rule_config(&self) -> RuleConfig {
105        let severity = match self.severity.to_lowercase().as_str() {
106            "error" => Severity::Error,
107            _ => Severity::Warning,
108        };
109
110        RuleConfig {
111            id: self.id.clone(),
112            severity,
113            message: self.message.clone(),
114            suggest: self.suggest.clone(),
115            glob: self.glob.clone(),
116            allowed_classes: self.allowed_classes.clone(),
117            token_map: self.token_map.clone(),
118            pattern: self.pattern.clone(),
119            max_count: self.max_count,
120            packages: self.packages.clone(),
121            regex: self.regex,
122            manifest: self.manifest.clone(),
123            exclude_glob: self.exclude_glob.clone(),
124            file_contains: self.file_contains.clone(),
125            file_not_contains: self.file_not_contains.clone(),
126            required_files: self.required_files.clone(),
127            forbidden_files: self.forbidden_files.clone(),
128            condition_pattern: self.condition_pattern.clone(),
129        }
130    }
131}