1use std::fmt;
2use std::sync::Arc;
3
4pub use crate::checks::{ViolationType, lookup_rationale};
5
6#[derive(Debug, Clone, Copy, serde::Serialize)]
8pub struct CheckRationale {
9 pub problem: &'static str,
11 pub fix: &'static str,
13 pub exception: &'static str,
15 pub llm_specific: bool,
17}
18
19impl fmt::Display for CheckRationale {
20 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21 writeln!(f, "Problem: {}", self.problem)?;
22 writeln!(f, "Fix: {}", self.fix)?;
23 writeln!(f, "Exception: {}", self.exception)?;
24 write!(f, "LLM-specific: {}", self.llm_specific)
25 }
26}
27
28impl ViolationType {
29 pub fn pattern(&self) -> Option<&str> {
31 match self {
32 Self::ForbiddenAttribute { pattern }
33 | Self::ForbiddenType { pattern }
34 | Self::ForbiddenCall { pattern }
35 | Self::ForbiddenMacro { pattern } => Some(pattern),
36 _ => None,
37 }
38 }
39}
40
41impl fmt::Display for ViolationType {
42 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43 write!(f, "{}", self.code())
44 }
45}
46
47#[derive(Debug, Clone)]
49pub struct Violation {
50 pub violation_type: ViolationType,
52 pub file_path: Arc<str>,
54 pub line: usize,
56 pub column: usize,
58 pub message: Box<str>,
60}
61
62impl Violation {
63 pub fn new(
65 violation_type: ViolationType,
66 file_path: Arc<str>,
67 line: usize,
68 column: usize,
69 message: impl Into<Box<str>>,
70 ) -> Self {
71 Self {
72 violation_type,
73 file_path,
74 line,
75 column,
76 message: message.into(),
77 }
78 }
79
80 pub fn rationale(&self) -> CheckRationale {
82 self.violation_type.rationale()
83 }
84}
85
86impl fmt::Display for Violation {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 write!(
89 f,
90 "{}:{}:{}: {}: {}",
91 self.file_path, self.line, self.column, self.violation_type, self.message
92 )
93 }
94}