Skip to main content

ass_core/analysis/styles/validation/
conflict.rs

1//! Style conflict detection and classification.
2//!
3//! Provides [`StyleConflict`] and [`ConflictType`] for detecting and
4//! describing conflicts such as duplicate names, circular inheritance, and
5//! missing references between styles.
6
7use alloc::{format, string::String, string::ToString, vec, vec::Vec};
8use core::fmt;
9
10use super::ValidationSeverity;
11
12/// Style conflict detection and classification
13#[derive(Debug, Clone)]
14pub struct StyleConflict<'a> {
15    /// Names of conflicting styles
16    pub styles: Vec<&'a str>,
17    /// Type of conflict detected
18    pub conflict_type: ConflictType,
19    /// Detailed conflict description
20    pub description: String,
21    /// Severity of the conflict
22    pub severity: ValidationSeverity,
23}
24
25/// Types of style conflicts that can be detected
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub enum ConflictType {
28    /// Multiple styles with identical names
29    DuplicateName,
30    /// Circular reference in style inheritance
31    CircularInheritance,
32    /// Conflicting property values between related styles
33    PropertyConflict,
34    /// Reference to non-existent style
35    MissingReference,
36}
37
38impl<'a> StyleConflict<'a> {
39    /// Create new style conflict
40    #[must_use]
41    pub fn new(
42        conflict_type: ConflictType,
43        styles: Vec<&'a str>,
44        description: &str,
45        severity: ValidationSeverity,
46    ) -> Self {
47        Self {
48            styles,
49            conflict_type,
50            description: description.to_string(),
51            severity,
52        }
53    }
54
55    /// Create duplicate name conflict
56    #[must_use]
57    pub fn duplicate_name(style_names: Vec<&'a str>) -> Self {
58        let description = format!("Duplicate style names found: {style_names:?}");
59        Self::new(
60            ConflictType::DuplicateName,
61            style_names,
62            &description,
63            ValidationSeverity::Error,
64        )
65    }
66
67    /// Create circular inheritance conflict
68    #[must_use]
69    pub fn circular_inheritance(cycle_styles: Vec<&'a str>) -> Self {
70        let description = format!("Circular inheritance detected: {cycle_styles:?}");
71        Self::new(
72            ConflictType::CircularInheritance,
73            cycle_styles,
74            &description,
75            ValidationSeverity::Error,
76        )
77    }
78
79    /// Create missing reference conflict
80    #[must_use]
81    pub fn missing_reference(referencing_style: &'a str, missing_style: &'a str) -> Self {
82        let description =
83            format!("Style '{referencing_style}' references non-existent style '{missing_style}'");
84        Self::new(
85            ConflictType::MissingReference,
86            vec![referencing_style],
87            &description,
88            ValidationSeverity::Error,
89        )
90    }
91
92    /// Create missing parent conflict
93    #[must_use]
94    pub fn missing_parent(style_name: &'a str, parent_name: &'a str) -> Self {
95        let description =
96            format!("Style '{style_name}' inherits from non-existent parent '{parent_name}'");
97        Self::new(
98            ConflictType::MissingReference,
99            vec![style_name],
100            &description,
101            ValidationSeverity::Warning,
102        )
103    }
104}
105
106impl fmt::Display for ConflictType {
107    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108        match self {
109            Self::DuplicateName => write!(f, "duplicate_name"),
110            Self::CircularInheritance => write!(f, "circular_inheritance"),
111            Self::PropertyConflict => write!(f, "property_conflict"),
112            Self::MissingReference => write!(f, "missing_reference"),
113        }
114    }
115}