use std::path::Path;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum Severity {
Error,
Warning,
Info,
Hint,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolDiagnostic {
pub tool: String,
pub file: String,
pub line: u32,
pub col: u32,
pub severity: Severity,
pub code: Option<String>,
pub message: String,
}
pub trait StaticTool: Send + Sync {
fn name(&self) -> &str;
fn language(&self) -> &str;
fn is_available(&self) -> bool;
fn run(&self, file: &Path, content: &str) -> anyhow::Result<Vec<ToolDiagnostic>>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn severity_serializes_lowercase() {
assert_eq!(
serde_json::to_string(&Severity::Error).expect("serialize"),
"\"error\""
);
assert_eq!(
serde_json::to_string(&Severity::Hint).expect("serialize"),
"\"hint\""
);
}
#[test]
fn diagnostic_round_trips() {
let d = ToolDiagnostic {
tool: "clippy".into(),
file: "src/main.rs".into(),
line: 12,
col: 4,
severity: Severity::Warning,
code: Some("clippy::needless_return".into()),
message: "unneeded return statement".into(),
};
let json = serde_json::to_string(&d).expect("serialize");
let back: ToolDiagnostic = serde_json::from_str(&json).expect("deserialize");
assert_eq!(back.tool, "clippy");
assert_eq!(back.line, 12);
assert_eq!(back.severity, Severity::Warning);
}
}