1pub mod allocation_rules;
2pub mod async_rules;
3pub mod database_rules;
4pub mod iter_rules;
5pub mod lock_across_await;
6pub mod memory_rules;
7pub mod registry;
8pub mod visitor;
9
10use crate::engine::AnalysisContext;
11use serde::{Deserialize, Serialize};
12use std::path::PathBuf;
13
14pub const MAX_FIX_TEXT_SIZE: usize = 10 * 1024; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, Default)]
21#[serde(rename_all = "lowercase")]
22pub enum Severity {
23 #[default]
24 Info,
25 Warning,
26 Error,
27}
28
29impl std::fmt::Display for Severity {
30 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 match self {
32 Severity::Info => write!(f, "info"),
33 Severity::Warning => write!(f, "warning"),
34 Severity::Error => write!(f, "error"),
35 }
36 }
37}
38
39impl std::str::FromStr for Severity {
40 type Err = String;
41
42 fn from_str(s: &str) -> Result<Self, Self::Err> {
43 match s.to_lowercase().as_str() {
44 "info" => Ok(Severity::Info),
45 "warning" | "warn" => Ok(Severity::Warning),
46 "error" | "deny" => Ok(Severity::Error),
47 _ => Err(format!("Unknown severity: {}", s)),
48 }
49 }
50}
51
52#[cfg(feature = "cli")]
56impl clap::ValueEnum for Severity {
57 fn value_variants<'a>() -> &'a [Self] {
58 &[Severity::Info, Severity::Warning, Severity::Error]
59 }
60
61 fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
62 match self {
63 Severity::Info => Some(clap::builder::PossibleValue::new("info")),
64 Severity::Warning => Some(clap::builder::PossibleValue::new("warning")),
65 Severity::Error => Some(clap::builder::PossibleValue::new("error")),
66 }
67 }
68}
69
70#[derive(Debug, Clone, Serialize)]
72pub struct Diagnostic {
73 pub rule_id: &'static str,
74 pub severity: Severity,
75 pub message: String,
76 pub file_path: PathBuf,
77 pub line: usize,
78 pub column: usize,
79 pub end_line: Option<usize>,
80 pub end_column: Option<usize>,
81 pub suggestion: Option<String>,
82 pub fix: Option<Fix>,
83}
84
85#[derive(Debug, Clone, Serialize)]
87pub struct Fix {
88 pub description: String,
89 pub replacements: Vec<Replacement>,
90}
91
92#[derive(Debug, Clone, Serialize)]
93pub struct Replacement {
94 pub file_path: PathBuf,
95 pub start_byte: usize,
96 pub end_byte: usize,
97 pub new_text: String,
98}
99
100pub trait Rule: Send + Sync {
102 fn id(&self) -> &'static str;
104
105 fn name(&self) -> &'static str;
107
108 fn description(&self) -> &'static str;
110
111 fn default_severity(&self) -> Severity;
113
114 fn check(&self, ctx: &AnalysisContext) -> Vec<Diagnostic>;
116}