#![cfg_attr(coverage_nightly, coverage(off))]
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;
use std::time::Duration;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ClippyDiagnostic {
pub code: String,
pub level: DiagnosticLevel,
pub message: String,
pub file: PathBuf,
pub line_start: usize,
pub line_end: usize,
pub column_start: usize,
pub column_end: usize,
pub suggestion: Option<String>,
}
impl ClippyDiagnostic {
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub fn from_json(json: &str) -> Result<Self> {
let value: serde_json::Value = serde_json::from_str(json)?;
Self::parse_json_value(&value)
}
fn parse_json_value(value: &serde_json::Value) -> Result<Self> {
let message = &value["message"];
let code = message["code"]["code"].as_str().unwrap_or("unknown");
let level = message["level"].as_str().unwrap_or("warning");
let spans = &message["spans"][0];
Ok(Self {
code: code.to_string(),
level: DiagnosticLevel::from_str(level),
message: message["message"].as_str().unwrap_or("").to_string(),
file: PathBuf::from(spans["file_name"].as_str().unwrap_or("")),
line_start: spans["line_start"].as_u64().unwrap_or(0) as usize,
line_end: spans["line_end"].as_u64().unwrap_or(0) as usize,
column_start: spans["column_start"].as_u64().unwrap_or(0) as usize,
column_end: spans["column_end"].as_u64().unwrap_or(0) as usize,
suggestion: None,
})
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum DiagnosticLevel {
Error,
Warning,
Note,
Help,
}
impl DiagnosticLevel {
fn from_str(s: &str) -> Self {
match s {
"error" => Self::Error,
"warning" => Self::Warning,
"note" => Self::Note,
_ => Self::Help,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ConfidenceLevel {
High, Medium, Low, }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FixResult {
pub success: bool,
pub diagnostic: ClippyDiagnostic,
pub modified_source: String,
pub confidence: ConfidenceLevel,
pub duration: Duration,
pub error: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FixReport {
pub total_diagnostics: usize,
pub successful_fixes: usize,
pub failed_fixes: usize,
pub skipped_low_confidence: usize,
pub success_rate: f64,
pub total_duration: Duration,
pub fixed_files: Vec<PathBuf>,
}
pub struct ClippyFixEngine {
cache: HashMap<String, FixResult>,
confidence_rules: HashMap<String, ConfidenceLevel>,
}
impl Default for ClippyFixEngine {
fn default() -> Self {
Self::new()
}
}
include!("clippy_fix_engine.rs");
include!("clippy_fix_tests.rs");