use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
#[serde(rename_all = "lowercase")]
pub enum Severity {
#[default]
Error,
Warning,
}
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct RuleSeverities {
pub max_lines: Option<Severity>,
pub max_depth: Option<Severity>,
pub max_imports: Option<Severity>,
pub max_repetition: Option<Severity>,
pub max_lines_per_function: Option<Severity>,
}
impl RuleSeverities {
#[must_use]
pub fn get(&self, rule: &str) -> Severity {
match rule {
"max-lines" => self.max_lines.unwrap_or(Severity::Error),
"max-depth" => self.max_depth.unwrap_or(Severity::Error),
"max-imports" => self.max_imports.unwrap_or(Severity::Error),
"max-repetition" => self.max_repetition.unwrap_or(Severity::Error),
"max-lines-per-function" => self.max_lines_per_function.unwrap_or(Severity::Error),
_ => Severity::Error,
}
}
pub fn extend(&mut self, other: &Self) {
if let Some(v) = other.max_lines {
self.max_lines = Some(v);
}
if let Some(v) = other.max_depth {
self.max_depth = Some(v);
}
if let Some(v) = other.max_imports {
self.max_imports = Some(v);
}
if let Some(v) = other.max_repetition {
self.max_repetition = Some(v);
}
if let Some(v) = other.max_lines_per_function {
self.max_lines_per_function = Some(v);
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct Thresholds {
#[serde(default = "default_max_lines")]
pub max_lines: usize,
#[serde(default = "default_max_depth")]
pub max_depth: usize,
#[serde(default = "default_max_imports")]
pub max_imports: usize,
#[serde(default = "default_max_repetition")]
pub max_repetition: f64,
#[serde(default = "default_min_duplicate_lines")]
pub min_duplicate_lines: usize,
#[serde(default = "default_max_lines_per_function")]
pub max_lines_per_function: usize,
}
#[must_use]
pub const fn default_max_lines() -> usize {
400
}
#[must_use]
pub const fn default_max_depth() -> usize {
6
}
#[must_use]
pub const fn default_max_imports() -> usize {
25
}
#[must_use]
pub const fn default_max_repetition() -> f64 {
15.0
}
#[must_use]
pub const fn default_min_duplicate_lines() -> usize {
4
}
#[must_use]
pub const fn default_max_lines_per_function() -> usize {
200
}
impl Default for Thresholds {
fn default() -> Self {
Self {
max_lines: 400,
max_depth: 6,
max_imports: 25,
max_repetition: 15.0,
min_duplicate_lines: 4,
max_lines_per_function: 200,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ThresholdsConfig {
#[serde(default)]
pub global: Thresholds,
#[serde(default)]
pub overrides: ThresholdsOverrides,
#[serde(default)]
pub severities: RuleSeverities,
}
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct ThresholdsOverrides {
pub rs: Option<PartialThresholds>,
pub py: Option<PartialThresholds>,
pub js: Option<PartialThresholds>,
pub ts: Option<PartialThresholds>,
pub java: Option<PartialThresholds>,
pub cs: Option<PartialThresholds>,
pub gd: Option<PartialThresholds>,
pub lua: Option<PartialThresholds>,
pub go: Option<PartialThresholds>,
pub php: Option<PartialThresholds>,
pub cpp: Option<PartialThresholds>,
#[serde(flatten)]
pub custom: HashMap<String, PartialThresholds>,
}
impl ThresholdsOverrides {
#[must_use]
pub fn get(&self, ext: &str) -> Option<&PartialThresholds> {
match ext {
"rs" => self.rs.as_ref(),
"py" => self.py.as_ref(),
"js" | "mjs" | "cjs" => self.js.as_ref(),
"ts" | "tsx" => self.ts.as_ref(),
"java" => self.java.as_ref(),
"cs" => self.cs.as_ref(),
"gd" => self.gd.as_ref(),
"lua" => self.lua.as_ref(),
"go" => self.go.as_ref(),
"php" => self.php.as_ref(),
"cpp" | "c" | "h" | "hpp" | "cc" | "cxx" | "hh" | "hxx" => self.cpp.as_ref(),
_ => self.custom.get(ext),
}
}
pub fn extend(&mut self, other: Self) {
if other.rs.is_some() {
self.rs = other.rs;
}
if other.py.is_some() {
self.py = other.py;
}
if other.js.is_some() {
self.js = other.js;
}
if other.ts.is_some() {
self.ts = other.ts;
}
if other.java.is_some() {
self.java = other.java;
}
if other.gd.is_some() {
self.gd = other.gd;
}
if other.cs.is_some() {
self.cs = other.cs;
}
if other.lua.is_some() {
self.lua = other.lua;
}
if other.go.is_some() {
self.go = other.go;
}
if other.php.is_some() {
self.php = other.php;
}
if other.cpp.is_some() {
self.cpp = other.cpp;
}
for (ext, partial) in other.custom {
self.custom.insert(ext, partial);
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
pub struct PartialThresholds {
pub max_lines: Option<usize>,
pub max_depth: Option<usize>,
pub max_imports: Option<usize>,
pub max_repetition: Option<f64>,
pub min_duplicate_lines: Option<usize>,
pub max_lines_per_function: Option<usize>,
}