pub mod perf;
pub mod security;
use std::path::{Path, PathBuf};
use oxc_ast::ast::Program;
use crate::cli::Category;
#[derive(Debug, Clone, serde::Serialize)]
pub struct Issue {
pub rule: String,
pub message: String,
pub file: PathBuf,
pub line: u32,
pub column: u32,
pub severity: Severity,
pub source: IssueSource,
pub category: IssueCategory,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, serde::Serialize)]
#[serde(rename_all = "lowercase")]
#[allow(dead_code)] pub enum Severity {
Info,
Low,
Medium,
High,
Critical,
}
impl std::fmt::Display for Severity {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Severity::Info => write!(f, "info"),
Severity::Low => write!(f, "low"),
Severity::Medium => write!(f, "medium"),
Severity::High => write!(f, "high"),
Severity::Critical => write!(f, "critical"),
}
}
}
#[derive(Debug, Clone, serde::Serialize)]
#[serde(rename_all = "kebab-case")]
#[allow(dead_code)]
pub enum IssueSource {
ReactPerfAnalyzer,
OxcLinter,
CargoAudit,
}
impl std::fmt::Display for IssueSource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
IssueSource::ReactPerfAnalyzer => write!(f, "react-perf-analyzer"),
IssueSource::OxcLinter => write!(f, "oxc-linter"),
IssueSource::CargoAudit => write!(f, "cargo-audit"),
}
}
}
#[derive(Debug, Clone, serde::Serialize)]
#[serde(rename_all = "lowercase")]
#[allow(dead_code)]
pub enum IssueCategory {
Performance,
Security,
Dependency,
}
impl std::fmt::Display for IssueCategory {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
IssueCategory::Performance => write!(f, "performance"),
IssueCategory::Security => write!(f, "security"),
IssueCategory::Dependency => write!(f, "dependency"),
}
}
}
pub struct RuleContext<'a> {
pub program: &'a Program<'a>,
pub source_text: &'a str,
pub file_path: &'a Path,
pub max_component_lines: usize,
}
pub trait Rule: Send + Sync {
#[allow(dead_code)]
fn name(&self) -> &str;
fn run(&self, ctx: &RuleContext<'_>) -> Vec<Issue>;
}
pub fn all_rules(category: &Category) -> Vec<Box<dyn Rule>> {
match category {
Category::Perf => perf::perf_rules(),
Category::Security => security::security_rules(),
Category::All => {
let mut r = perf::perf_rules();
r.extend(security::security_rules());
r
}
}
}