use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use crate::{SourceFile, SourceModel};
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, JsonSchema, Default,
)]
#[serde(rename_all = "lowercase")]
pub enum Severity {
#[default]
Hint,
Warning,
Error,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Default)]
#[serde(rename_all = "snake_case")]
pub enum SmellCategory {
#[default]
Bloaters,
OoAbusers,
ChangePreventers,
Dispensables,
Couplers,
Security,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
pub struct Location {
pub path: PathBuf,
pub start_line: usize,
#[serde(default, skip_serializing_if = "crate::is_zero_usize")]
pub start_col: usize,
pub end_line: usize,
#[serde(default, skip_serializing_if = "crate::is_zero_usize")]
pub end_col: usize,
pub name: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
pub struct Finding {
pub smell_name: String,
pub category: SmellCategory,
pub severity: Severity,
pub location: Location,
pub message: String,
pub suggested_refactorings: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub actual_value: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub threshold: Option<f64>,
}
pub struct AnalysisContext<'a> {
pub file: &'a SourceFile,
pub model: &'a SourceModel,
}
pub trait Plugin: Send + Sync {
fn name(&self) -> &str;
fn version(&self) -> &str {
env!("CARGO_PKG_VERSION")
}
fn description(&self) -> &str {
""
}
fn authors(&self) -> Vec<String> {
vec![env!("CARGO_PKG_AUTHORS").to_string()]
}
fn smells(&self) -> Vec<String> {
Vec::new()
}
fn analyze(&self, ctx: &AnalysisContext) -> Vec<Finding>;
}
pub fn func_location(path: &std::path::Path, f: &crate::FunctionInfo) -> Location {
Location {
path: path.into(),
start_line: f.start_line,
start_col: f.name_col,
end_line: f.start_line,
end_col: f.name_end_col,
name: Some(f.name.clone()),
}
}
pub fn class_location(path: &std::path::Path, c: &crate::ClassInfo) -> Location {
Location {
path: path.into(),
start_line: c.start_line,
start_col: c.name_col,
end_line: c.start_line,
end_col: c.name_end_col,
name: Some(c.name.clone()),
}
}