1use std::sync::LazyLock;
9
10use fallow_config::{ExternalPluginDef, FallowConfig, RulePackDef, RulesConfig};
11
12static DEFAULT_RULE_SEVERITIES: LazyLock<serde_json::Value> = LazyLock::new(|| {
15 serde_json::to_value(RulesConfig::default())
16 .unwrap_or_else(|_| serde_json::Value::Object(serde_json::Map::new()))
17});
18
19#[must_use]
21pub fn config_schema() -> serde_json::Value {
22 FallowConfig::json_schema()
23}
24
25#[must_use]
27pub fn plugin_schema() -> serde_json::Value {
28 ExternalPluginDef::json_schema()
29}
30
31#[must_use]
33pub fn rule_pack_schema() -> serde_json::Value {
34 RulePackDef::json_schema()
35}
36
37#[cfg(feature = "schema")]
40#[must_use]
41pub fn similar_code_snapshot_schema() -> serde_json::Value {
42 fallow_output::SimilarCodeCandidateSnapshot::json_schema()
43}
44
45#[must_use]
53pub fn default_rule_severities() -> serde_json::Value {
54 DEFAULT_RULE_SEVERITIES.clone()
55}
56
57#[must_use]
60pub fn is_rule_severity_key(key: &str) -> bool {
61 DEFAULT_RULE_SEVERITIES
62 .get(key)
63 .is_some_and(serde_json::Value::is_string)
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69
70 #[test]
71 fn schemas_are_json_objects_with_properties() {
72 for (label, schema) in [
73 ("config", config_schema()),
74 ("plugin", plugin_schema()),
75 ("rule-pack", rule_pack_schema()),
76 ] {
77 assert!(
78 schema
79 .get("properties")
80 .is_some_and(serde_json::Value::is_object),
81 "{label} schema must be an object schema with properties"
82 );
83 }
84 }
85
86 #[test]
87 fn default_severities_are_keyed_by_config_key() {
88 let defaults = default_rule_severities();
89 assert_eq!(defaults["unused-exports"], "error");
90 assert_eq!(defaults["security-sink"], "off");
91 assert!(
92 defaults.get("unused_exports").is_none(),
93 "keys are kebab-case"
94 );
95 assert!(is_rule_severity_key("coverage-gaps"));
96 assert!(!is_rule_severity_key("code-duplication"));
97 }
98}