1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
//! Rule Registry - Central metadata for all linter rules.
//!
//! Provides a central registry of all linter rules with their metadata,
//! including shell compatibility information. Use this to query which rules
//! apply to specific shell types.
//!
//! # Examples
//!
//! ## Checking rule compatibility
//!
//! ```
//! use bashrs::linter::rule_registry;
//! use bashrs::linter::ShellType;
//!
//! // Check if a rule applies to bash
//! assert!(rule_registry::should_apply_rule("SEC001", ShellType::Bash));
//!
//! // Check if a rule applies to POSIX sh
//! assert!(rule_registry::should_apply_rule("IDEM001", ShellType::Sh));
//! ```
//!
//! ## Getting rule metadata
//!
//! ```
//! use bashrs::linter::rule_registry;
//!
//! if let Some(compat) = rule_registry::get_rule_compatibility("SEC001") {
//! println!("SEC001 compatibility: {:?}", compat);
//! }
//! ```
use crateShellCompatibility;
use HashMap;
/// Metadata for a linter rule, including shell compatibility.
///
/// Each rule has a unique ID, descriptive name, and compatibility specification
/// indicating which shell types the rule applies to.
///
/// # Examples
///
/// ## Accessing metadata from registry
///
/// ```
/// use bashrs::linter::rule_registry;
///
/// // Get compatibility for a security rule
/// let compat = rule_registry::get_rule_compatibility("SEC001");
/// assert!(compat.is_some());
/// ```
///
/// # Fields
///
/// * `id` - Unique rule identifier (e.g., "SEC001", "DET001", "IDEM001")
/// * `name` - Human-readable rule description
/// * `compatibility` - Shell compatibility specification
/// Gets the shell compatibility for a specific rule ID.
///
/// Returns the compatibility specification if the rule exists in the registry.
///
/// # Arguments
///
/// * `rule_id` - The rule identifier (e.g., "SEC001", "DET001")
///
/// # Returns
///
/// * `Some(ShellCompatibility)` - If rule exists in registry
/// * `None` - If rule ID not found
///
/// # Examples
///
/// ## Check security rule compatibility
///
/// ```
/// use bashrs::linter::rule_registry;
/// use bashrs::linter::ShellCompatibility;
///
/// let compat = rule_registry::get_rule_compatibility("SEC001");
/// assert_eq!(compat, Some(ShellCompatibility::Universal));
/// ```
///
/// ## Handle unknown rules
///
/// ```
/// use bashrs::linter::rule_registry;
///
/// let compat = rule_registry::get_rule_compatibility("UNKNOWN");
/// assert!(compat.is_none());
/// ```
/// Returns metadata for a specific rule by ID.
/// Returns all rule metadata entries sorted by ID.
/// Checks if a rule should be applied for a given shell type.
///
/// Queries the rule registry and checks if the rule's compatibility
/// specification matches the target shell type.
///
/// # Arguments
///
/// * `rule_id` - The rule identifier to check
/// * `shell` - The target shell type
///
/// # Returns
///
/// * `true` - If rule applies to the shell type (or rule not in registry)
/// * `false` - If rule explicitly doesn't apply to the shell type
///
/// # Conservative Default
///
/// If a rule is not found in the registry, this function returns `true`
/// (conservative approach - assume rule applies unless explicitly excluded).
///
/// # Examples
///
/// ## Security rules (universal)
///
/// ```
/// use bashrs::linter::rule_registry;
/// use bashrs::linter::ShellType;
///
/// // Security rules apply to all shells
/// assert!(rule_registry::should_apply_rule("SEC001", ShellType::Bash));
/// assert!(rule_registry::should_apply_rule("SEC001", ShellType::Sh));
/// assert!(rule_registry::should_apply_rule("SEC001", ShellType::Zsh));
/// ```
///
/// ## Filtering by shell type
///
/// ```
/// use bashrs::linter::rule_registry;
/// use bashrs::linter::ShellType;
///
/// // Only apply rules that match the target shell
/// let rules_to_check = vec!["SEC001", "DET001", "IDEM001"];
/// let bash_rules: Vec<_> = rules_to_check
/// .into_iter()
/// .filter(|&rule| rule_registry::should_apply_rule(rule, ShellType::Bash))
/// .collect();
///
/// assert_eq!(bash_rules.len(), 3); // All universal rules
/// ```
///
/// ## Unknown rules default to applying
///
/// ```
/// use bashrs::linter::rule_registry;
/// use bashrs::linter::ShellType;
///
/// // Unknown rules conservatively apply
/// assert!(rule_registry::should_apply_rule("UNKNOWN", ShellType::Bash));
/// ```
lazy_static!