Skip to main content

ass_core/analysis/linting/rules/
builtin.rs

1//! Built-in lint rule registry aggregating all rule implementations.
2//!
3//! Houses the [`BuiltinRules`] facade used to enumerate, filter, and look up
4//! the complete set of built-in linting rules.
5
6use alloc::{boxed::Box, vec, vec::Vec};
7
8use super::{
9    AccessibilityRule, EncodingRule, InvalidColorRule, InvalidTagRule, MissingStyleRule,
10    NegativeDurationRule, PerformanceRule, TimingOverlapRule,
11};
12use crate::analysis::linting::{IssueCategory, LintRule};
13
14/// Built-in lint rules registry
15///
16/// Provides access to all built-in rules that check for common issues
17/// in ASS subtitle scripts. Rules are organized by category and can be
18/// used individually or as a complete set.
19///
20/// # Performance
21///
22/// All rules are designed for efficient execution with minimal memory
23/// overhead. Most rules have O(n) or O(n log n) time complexity.
24///
25/// # Rule List
26///
27/// - `TimingOverlapRule`: Detects overlapping dialogue events
28/// - `NegativeDurationRule`: Finds events with invalid durations
29/// - `InvalidColorRule`: Validates color formats in styles and tags
30/// - `MissingStyleRule`: Checks for undefined style references
31/// - `InvalidTagRule`: Detects malformed override tags
32/// - `PerformanceRule`: Identifies performance-impacting patterns
33/// - `EncodingRule`: Validates text encoding and character usage
34/// - `AccessibilityRule`: Ensures readability and compatibility
35pub struct BuiltinRules;
36
37impl BuiltinRules {
38    /// Get all built-in linting rules
39    ///
40    /// Returns a vector of all available built-in rules ready for use.
41    /// Rules are returned in their default configuration with standard
42    /// severity levels and categories.
43    ///
44    /// # Example
45    ///
46    /// ```rust
47    /// use ass_core::analysis::linting::rules::BuiltinRules;
48    ///
49    /// let rules = BuiltinRules::all_rules();
50    /// assert_eq!(rules.len(), 8); // All built-in rules
51    /// ```
52    #[must_use]
53    pub fn all_rules() -> Vec<Box<dyn LintRule>> {
54        vec![
55            Box::new(TimingOverlapRule),
56            Box::new(NegativeDurationRule),
57            Box::new(InvalidColorRule),
58            Box::new(MissingStyleRule),
59            Box::new(InvalidTagRule),
60            Box::new(PerformanceRule),
61            Box::new(EncodingRule),
62            Box::new(AccessibilityRule),
63        ]
64    }
65
66    /// Get rules by category
67    ///
68    /// Returns only rules that check issues in the specified category.
69    /// Useful for focused linting or when only certain types of issues
70    /// need to be checked.
71    ///
72    /// # Arguments
73    ///
74    /// * `category` - The issue category to filter by
75    ///
76    /// # Example
77    ///
78    /// ```rust
79    /// use ass_core::analysis::linting::{IssueCategory, rules::BuiltinRules};
80    ///
81    /// let timing_rules = BuiltinRules::rules_for_category(IssueCategory::Timing);
82    /// // Returns timing-related rules only
83    /// ```
84    #[must_use]
85    pub fn rules_for_category(category: IssueCategory) -> Vec<Box<dyn LintRule>> {
86        Self::all_rules()
87            .into_iter()
88            .filter(|rule| rule.category() == category)
89            .collect()
90    }
91
92    /// Get rule by ID
93    ///
94    /// Returns the rule with the specified ID, or None if no such rule exists.
95    /// Rule IDs are unique identifiers used for configuration and reporting.
96    ///
97    /// # Arguments
98    ///
99    /// * `id` - The rule ID to search for
100    ///
101    /// # Example
102    ///
103    /// ```rust
104    /// use ass_core::analysis::linting::rules::BuiltinRules;
105    ///
106    /// let rule = BuiltinRules::rule_by_id("timing-overlap");
107    /// assert!(rule.is_some());
108    /// assert_eq!(rule.unwrap().id(), "timing-overlap");
109    /// ```
110    #[must_use]
111    pub fn rule_by_id(id: &str) -> Option<Box<dyn LintRule>> {
112        Self::all_rules().into_iter().find(|rule| rule.id() == id)
113    }
114
115    /// Get all rule IDs
116    ///
117    /// Returns a vector of all available rule IDs for configuration
118    /// and reporting purposes.
119    ///
120    /// # Example
121    ///
122    /// ```rust
123    /// use ass_core::analysis::linting::rules::BuiltinRules;
124    ///
125    /// let ids = BuiltinRules::all_rule_ids();
126    /// assert!(ids.contains(&"timing-overlap"));
127    /// assert!(ids.contains(&"negative-duration"));
128    /// ```
129    #[must_use]
130    pub fn all_rule_ids() -> Vec<&'static str> {
131        Self::all_rules().iter().map(|rule| rule.id()).collect()
132    }
133}