pub mod analyzer;
pub mod background;
pub mod diff;
pub mod notifier;
pub mod platform;
pub mod prompts;
pub mod report;
pub mod reviewer;
pub mod fixer;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::fmt;
use std::path::PathBuf;
use std::str::FromStr;
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum AutoFixMode {
Pr,
Commit,
#[default]
Apply,
}
impl FromStr for AutoFixMode {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"pr" => Ok(AutoFixMode::Pr),
"commit" => Ok(AutoFixMode::Commit),
"apply" => Ok(AutoFixMode::Apply),
_ => Err(format!(
"invalid auto-fix mode '{}': expected pr, commit, or apply",
s
)),
}
}
}
impl fmt::Display for AutoFixMode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AutoFixMode::Pr => write!(f, "pr"),
AutoFixMode::Commit => write!(f, "commit"),
AutoFixMode::Apply => write!(f, "apply"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Assessment {
Ready,
NeedsWork,
CriticalIssues,
}
impl fmt::Display for Assessment {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Assessment::Ready => write!(f, "Ready"),
Assessment::NeedsWork => write!(f, "Needs Work"),
Assessment::CriticalIssues => write!(f, "Critical Issues"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum Severity {
Critical,
Important,
Minor,
}
impl fmt::Display for Severity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Severity::Critical => write!(f, "Critical"),
Severity::Important => write!(f, "Important"),
Severity::Minor => write!(f, "Minor"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReviewIssue {
pub severity: Severity,
pub category: String,
pub file: PathBuf,
pub line: Option<u32>,
pub message: String,
pub suggestion: Option<String>,
}
impl fmt::Display for ReviewIssue {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"[{}] {} ({}): {}",
self.severity,
self.file.display(),
self.category,
self.message
)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReviewSummary {
pub files_reviewed: usize,
pub total_issues: usize,
pub critical_count: usize,
pub important_count: usize,
pub minor_count: usize,
pub assessment: Assessment,
pub summary_text: String,
}
impl fmt::Display for ReviewSummary {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Review: {} ({} files, {} issues: {} critical, {} important, {} minor)",
self.assessment,
self.files_reviewed,
self.total_issues,
self.critical_count,
self.important_count,
self.minor_count
)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum FileStatus {
Added,
Modified,
Deleted,
Renamed { from: PathBuf },
}
impl fmt::Display for FileStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FileStatus::Added => write!(f, "Added"),
FileStatus::Modified => write!(f, "Modified"),
FileStatus::Deleted => write!(f, "Deleted"),
FileStatus::Renamed { from } => {
write!(f, "Renamed from {}", from.display())
}
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReviewedFile {
pub path: PathBuf,
pub status: FileStatus,
pub issues: Vec<ReviewIssue>,
}
impl fmt::Display for ReviewedFile {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{} ({}, {} issues)",
self.path.display(),
self.status,
self.issues.len()
)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AutoFix {
pub file: PathBuf,
pub line: Option<u32>,
pub description: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReviewResult {
pub summary: ReviewSummary,
pub files: Vec<ReviewedFile>,
pub issues: Vec<ReviewIssue>,
pub base_ref: String,
pub head_ref: String,
#[serde(default)]
pub auto_fixes: Vec<AutoFix>,
}
impl ReviewResult {
pub fn count_by_severity(&self) -> HashMap<Severity, usize> {
let mut counts = HashMap::new();
for issue in &self.issues {
*counts.entry(issue.severity).or_insert(0) += 1;
}
counts
}
}
impl fmt::Display for ReviewResult {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Review {}..{}: {}",
self.base_ref, self.head_ref, self.summary
)
}
}