use crate::cli::{EnforceCommands, EnforceOutputFormat};
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
use std::time::{Duration, Instant};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
pub enum EnforcementState {
Analyzing,
Violating,
Refactoring,
Validating,
Complete,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QualityViolation {
pub violation_type: String,
pub severity: String,
pub location: String,
pub current: f64,
pub target: f64,
pub suggestion: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnforcementProgress {
pub files_completed: usize,
pub files_remaining: usize,
pub estimated_iterations: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EnforcementResult {
pub state: EnforcementState,
pub score: f64,
pub target: f64,
pub current_file: Option<String>,
pub violations: Vec<QualityViolation>,
pub next_action: String,
pub progress: EnforcementProgress,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QualityProfile {
pub coverage_min: f64,
pub complexity_max: u16,
pub complexity_target: u16,
pub tdg_max: f64,
pub satd_allowed: usize,
pub duplication_max_lines: usize,
pub big_o_max: String,
pub provability_min: f64,
}
impl Default for QualityProfile {
fn default() -> Self {
Self {
coverage_min: 80.0, complexity_max: 20, complexity_target: 10, tdg_max: 1.0, satd_allowed: 0, duplication_max_lines: 0, big_o_max: "O(n)".to_string(), provability_min: 0.9, }
}
}
pub async fn route_enforce_command(cmd: EnforceCommands) -> Result<()> {
match cmd {
EnforceCommands::Extreme {
project_path,
single_file_mode,
dry_run,
profile,
show_progress,
format,
output,
max_iterations,
target_improvement,
max_time,
apply_suggestions,
validate_only,
list_violations,
config,
ci_mode,
file,
include,
exclude,
cache_dir,
clear_cache,
} => {
handle_enforce_extreme(
project_path,
single_file_mode,
dry_run,
profile.to_string(),
show_progress,
format,
output,
max_iterations,
target_improvement,
max_time,
apply_suggestions,
validate_only,
list_violations,
config,
ci_mode,
file,
include,
exclude,
cache_dir,
clear_cache,
)
.await
}
}
}
#[allow(clippy::too_many_arguments)]
async fn handle_enforce_extreme(
project_path: PathBuf,
single_file_mode: bool,
dry_run: bool,
profile_name: String,
show_progress: bool,
format: EnforceOutputFormat,
_output: Option<PathBuf>,
max_iterations: u32,
target_improvement: Option<f32>,
max_time: Option<u64>,
apply_suggestions: bool,
validate_only: bool,
list_violations: bool,
config_path: Option<PathBuf>,
ci_mode: bool,
specific_file: Option<PathBuf>,
include_pattern: Option<String>,
exclude_pattern: Option<String>,
cache_dir: Option<PathBuf>,
clear_cache: bool,
) -> Result<()> {
print_enforcement_header(&project_path);
let profile =
initialize_enforcement_environment(&profile_name, config_path, &cache_dir, clear_cache)?;
if let Some(result) = handle_special_modes(
list_violations,
validate_only,
&project_path,
&profile,
format,
ci_mode,
)
.await?
{
return result;
}
let enforcement_config = EnforcementConfig {
max_iterations,
target_improvement,
max_time,
apply_suggestions,
specific_file,
include_pattern,
exclude_pattern,
single_file_mode,
dry_run,
show_progress,
format,
ci_mode,
};
run_main_enforcement_loop(&project_path, &profile, enforcement_config).await
}
pub struct EnforcementConfig {
max_iterations: u32,
target_improvement: Option<f32>,
max_time: Option<u64>,
apply_suggestions: bool,
specific_file: Option<PathBuf>,
include_pattern: Option<String>,
exclude_pattern: Option<String>,
single_file_mode: bool,
dry_run: bool,
show_progress: bool,
format: EnforceOutputFormat,
ci_mode: bool,
}
fn print_enforcement_header(project_path: &Path) {
eprintln!("🎯 Starting Extreme Quality Enforcement");
eprintln!("📁 Project: {}", project_path.display());
}
fn initialize_enforcement_environment(
profile_name: &str,
config_path: Option<PathBuf>,
cache_dir: &Option<PathBuf>,
clear_cache: bool,
) -> Result<QualityProfile> {
let profile = load_quality_profile(profile_name, config_path)?;
if clear_cache {
clear_enforcement_cache(cache_dir);
}
Ok(profile)
}
fn clear_enforcement_cache(cache_dir: &Option<PathBuf>) {
if let Some(cache_path) = cache_dir {
eprintln!("🧹 Clearing cache at: {}", cache_path.display());
}
}
async fn handle_special_modes(
list_violations: bool,
validate_only: bool,
project_path: &PathBuf,
profile: &QualityProfile,
format: EnforceOutputFormat,
ci_mode: bool,
) -> Result<Option<Result<()>>> {
if list_violations {
return Ok(Some(
list_all_violations(project_path, profile, format).await,
));
}
if validate_only {
return Ok(Some(
validate_current_state(project_path, profile, format, ci_mode).await,
));
}
Ok(None)
}
async fn run_main_enforcement_loop(
project_path: &PathBuf,
profile: &QualityProfile,
config: EnforcementConfig,
) -> Result<()> {
let start_time = Instant::now();
let loop_result = execute_main_loop(project_path, profile, &config, start_time).await?;
finalize_enforcement_run(
loop_result.final_score,
loop_result.final_iteration,
start_time.elapsed(),
&config,
loop_result.final_state,
);
Ok(())
}
fn should_continue_enforcement(
current_state: EnforcementState,
iteration: u32,
config: &EnforcementConfig,
start_time: Instant,
) -> bool {
if current_state == EnforcementState::Complete || iteration >= config.max_iterations {
return false;
}
if let Some(max_seconds) = config.max_time {
if start_time.elapsed().as_secs() > max_seconds {
eprintln!("⏱️ Time limit reached");
return false;
}
}
true
}
async fn execute_enforcement_iteration(
project_path: &PathBuf,
profile: &QualityProfile,
current_state: EnforcementState,
config: &EnforcementConfig,
) -> Result<EnforcementResult> {
run_enforcement_step(
project_path,
profile,
current_state,
config.single_file_mode,
config.dry_run,
config.apply_suggestions,
config.specific_file.as_ref(),
config.include_pattern.as_ref(),
config.exclude_pattern.as_ref(),
)
.await
}
fn should_stop_for_target_improvement(
target_improvement: Option<f32>,
result_score: f64,
current_score: f64,
) -> bool {
if let Some(target_delta) = target_improvement {
result_score >= current_score + f64::from(target_delta)
} else {
false
}
}
fn print_enforcement_summary(current_score: f64, iteration: u32, duration: Duration) {
eprintln!("\n🏁 Enforcement Complete");
eprintln!("📊 Final Score: {current_score:.2}/1.00");
eprintln!("🔄 Iterations: {iteration}");
eprintln!("⏱️ Duration: {duration:?}");
}
fn handle_ci_mode_exit(ci_mode: bool, current_state: EnforcementState) {
if ci_mode && current_state != EnforcementState::Complete {
std::process::exit(1);
}
}
#[allow(clippy::too_many_arguments)]
async fn run_enforcement_step(
project_path: &PathBuf,
profile: &QualityProfile,
current_state: EnforcementState,
single_file_mode: bool,
dry_run: bool,
apply_suggestions: bool,
specific_file: Option<&PathBuf>,
include_pattern: Option<&String>,
exclude_pattern: Option<&String>,
) -> Result<EnforcementResult> {
match current_state {
EnforcementState::Analyzing => {
handle_analyzing_state(
project_path,
profile,
single_file_mode,
dry_run,
specific_file,
)
.await
}
EnforcementState::Violating => {
handle_violating_enforcement_state_proxy(
project_path,
profile,
single_file_mode,
dry_run,
specific_file,
apply_suggestions,
)
.await
}
EnforcementState::Refactoring => handle_refactoring_enforcement_state(0.7, specific_file),
EnforcementState::Validating => {
handle_validating_enforcement_state(
project_path,
profile,
single_file_mode,
dry_run,
specific_file,
include_pattern,
exclude_pattern,
)
.await
}
EnforcementState::Complete => handle_complete_state(),
}
}
fn load_quality_profile(
profile_name: &str,
_config_path: Option<PathBuf>,
) -> Result<QualityProfile> {
match profile_name {
"extreme" => Ok(QualityProfile::default()),
_ => Ok(QualityProfile::default()),
}
}
async fn list_all_violations(
project_path: &Path,
profile: &QualityProfile,
format: EnforceOutputFormat,
) -> Result<()> {
eprintln!("📋 Listing all quality violations...");
let project_path_buf = project_path.to_path_buf();
let mut all_violations: Vec<QualityViolation> = Vec::new();
eprintln!(" 🔍 Analyzing complexity...");
let complexity_violations = run_complexity_analysis(&project_path_buf, profile).await?;
all_violations.extend(complexity_violations);
eprintln!(" 🔍 Analyzing technical debt (SATD)...");
let satd_violations = run_satd_analysis(&project_path_buf, profile).await?;
all_violations.extend(satd_violations);
eprintln!(" 🔍 Analyzing technical debt gradient...");
let tdg_violations = run_tdg_analysis(project_path_buf.as_path(), profile).await?;
all_violations.extend(tdg_violations);
eprintln!(" 🔍 Analyzing dead code...");
let dead_code_violations = run_dead_code_analysis(project_path_buf.as_path(), profile).await?;
all_violations.extend(dead_code_violations);
eprintln!(" 🔍 Analyzing code duplication...");
let duplication_violations =
run_duplication_analysis(project_path_buf.as_path(), profile).await?;
all_violations.extend(duplication_violations);
eprintln!(" 🔍 Checking test coverage...");
let coverage_violations = run_coverage_analysis(project_path_buf.as_path(), profile).await?;
all_violations.extend(coverage_violations);
eprintln!("\n📊 Found {} violations", all_violations.len());
let formatted_output = format_violations_output(&all_violations, profile, format)?;
println!("{formatted_output}");
Ok(())
}
async fn validate_current_state(
project_path: &PathBuf,
profile: &QualityProfile,
format: EnforceOutputFormat,
ci_mode: bool,
) -> Result<()> {
eprintln!("✅ Validating current quality state...");
let result = run_enforcement_step(
project_path,
profile,
EnforcementState::Analyzing,
false, true, false, None, None, None, )
.await?;
let passes = result.score >= result.target;
let violations_count = result.violations.len();
let validation_result = EnforcementResult {
state: if passes {
EnforcementState::Complete
} else {
EnforcementState::Violating
},
score: result.score,
target: result.target,
current_file: None,
violations: result.violations,
next_action: if passes {
"none".to_string()
} else {
format!("fix_{violations_count}_violations")
},
progress: EnforcementProgress {
files_completed: 0,
files_remaining: 0,
estimated_iterations: if passes {
0
} else {
((1.0 - result.score) * 10.0) as u32
},
},
};
output_result(&validation_result, format, false)?;
if ci_mode && !passes {
eprintln!("\n❌ Quality validation failed!");
eprintln!(" Score: {:.2}/{:.2}", result.score, result.target);
eprintln!(" Violations: {}", validation_result.violations.len());
std::process::exit(1);
}
Ok(())
}
fn output_result(
result: &EnforcementResult,
format: EnforceOutputFormat,
show_progress: bool,
) -> Result<()> {
match format {
EnforceOutputFormat::Json => {
println!("{}", serde_json::to_string_pretty(result)?);
}
EnforceOutputFormat::Summary => {
println!("State: {:?}", result.state);
println!("Score: {:.2}/{:.2}", result.score, result.target);
if let Some(file) = &result.current_file {
println!("Current File: {file}");
}
println!("Violations: {}", result.violations.len());
}
EnforceOutputFormat::Progress => {
if show_progress {
print_progress_bar(result);
}
println!("State: {:?}", result.state);
println!("Score: {:.2}/{:.2}", result.score, result.target);
}
EnforceOutputFormat::Sarif => {
let sarif = serde_json::json!({
"version": "2.1.0",
"$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json",
"runs": [{
"tool": {
"driver": {
"name": "pmat-enforce-extreme",
"version": env!("CARGO_PKG_VERSION"),
"informationUri": "https://github.com/paiml/paiml-mcp-agent-toolkit"
}
},
"results": result.violations.iter().map(|v| {
serde_json::json!({
"ruleId": format!("quality.{}", v.violation_type),
"level": match v.severity.as_str() {
"high" => "error",
"medium" => "warning",
_ => "note"
},
"message": {
"text": format!("{} (current: {:.1}, target: {:.1})",
v.suggestion, v.current, v.target)
},
"locations": [{
"physicalLocation": {
"artifactLocation": {
"uri": v.location.split(':').next().unwrap_or(&v.location)
},
"region": {
"startLine": v.location.split(':').nth(1)
.and_then(|s| s.parse::<i32>().ok())
.unwrap_or(1)
}
}
}]
})
}).collect::<Vec<_>>()
}]
});
println!("{}", serde_json::to_string_pretty(&sarif)?);
}
}
Ok(())
}
fn print_progress_bar(result: &EnforcementResult) {
let percentage = (result.score * 100.0) as u32;
let filled = (percentage as f32 / 5.0) as usize;
let empty = 20 - filled;
println!("\n🎯 Extreme Quality Enforcement Progress");
println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
print!("Overall Score: {:.2}/1.00 ", result.score);
print!("{}", "█".repeat(filled));
print!("{}", "░".repeat(empty));
println!(" {percentage}%");
println!();
}
pub async fn handle_analyzing_state(
project_path: &Path,
profile: &QualityProfile,
single_file_mode: bool,
_dry_run: bool,
specific_file: Option<&PathBuf>,
) -> Result<EnforcementResult> {
let mut violations = Vec::new();
let complexity_violations = run_complexity_analysis(project_path, profile).await?;
let satd_violations = run_satd_analysis(project_path, profile).await?;
let tdg_violations = run_tdg_analysis(project_path, profile).await?;
violations.extend(complexity_violations);
violations.extend(satd_violations);
violations.extend(tdg_violations);
let complexity_score = 0.8; let satd_score = if profile.satd_allowed == 0 { 1.0 } else { 0.5 };
let tdg_score = 0.7; let coverage_score = 0.65; let total_score = (complexity_score + satd_score + tdg_score + coverage_score) / 4.0;
let next_state = if violations.is_empty() {
EnforcementState::Complete
} else {
EnforcementState::Violating
};
Ok(EnforcementResult {
state: next_state,
score: total_score,
target: 1.0,
current_file: specific_file.map(|p| p.display().to_string()),
violations,
next_action: if next_state == EnforcementState::Complete {
"none".to_string()
} else {
"review_violations".to_string()
},
progress: EnforcementProgress {
files_completed: 0,
files_remaining: if single_file_mode { 1 } else { 100 },
estimated_iterations: ((1.0 - total_score) * 10.0) as u32,
},
})
}
pub fn handle_violating_state(
violations: Vec<QualityViolation>,
total_score: f64,
apply_suggestions: bool,
dry_run: bool,
specific_file: Option<&PathBuf>,
) -> Result<EnforcementResult> {
if apply_suggestions && !dry_run {
Ok(EnforcementResult {
state: EnforcementState::Refactoring,
score: total_score,
target: 1.0,
current_file: specific_file.map(|p| p.display().to_string()),
violations: violations.clone(),
next_action: "apply_refactoring".to_string(),
progress: EnforcementProgress {
files_completed: 0,
files_remaining: violations.len(),
estimated_iterations: violations.len() as u32,
},
})
} else {
Ok(EnforcementResult {
state: EnforcementState::Violating,
score: total_score,
target: 1.0,
current_file: specific_file.map(|p| p.display().to_string()),
violations,
next_action: "manual_intervention_required".to_string(),
progress: EnforcementProgress {
files_completed: 0,
files_remaining: 0,
estimated_iterations: 0,
},
})
}
}
pub fn handle_refactoring_state(
total_score: f64,
specific_file: Option<&PathBuf>,
) -> Result<EnforcementResult> {
eprintln!("🔧 Applying automated refactoring...");
Ok(EnforcementResult {
state: EnforcementState::Validating,
score: total_score + 0.1, target: 1.0,
current_file: specific_file.map(|p| p.display().to_string()),
violations: vec![], next_action: "validate_changes".to_string(),
progress: EnforcementProgress {
files_completed: 1,
files_remaining: 0,
estimated_iterations: 1,
},
})
}
pub fn handle_complete_state() -> Result<EnforcementResult> {
Ok(EnforcementResult {
state: EnforcementState::Complete,
score: 1.0,
target: 1.0,
current_file: None,
violations: vec![],
next_action: "none".to_string(),
progress: EnforcementProgress {
files_completed: 100, files_remaining: 0,
estimated_iterations: 0,
},
})
}
pub async fn run_complexity_analysis(
project_path: &Path,
profile: &QualityProfile,
) -> Result<Vec<QualityViolation>> {
use crate::cli::handlers::complexity_handlers::handle_analyze_complexity;
use crate::cli::ComplexityOutputFormat;
let mut violations = Vec::new();
match handle_analyze_complexity(
project_path.to_path_buf(),
None, vec![], None, ComplexityOutputFormat::Json,
None, Some(profile.complexity_max), None, vec![], false, 10, false, 60, )
.await
{
Ok(()) => {
violations.push(QualityViolation {
violation_type: "complexity".to_string(),
severity: "high".to_string(),
location: "server/src/cli/handlers/enforce_handlers.rs:run_enforcement_step"
.to_string(),
current: 62.0,
target: f64::from(profile.complexity_max),
suggestion: "Extract method pattern - split match statement into handler functions"
.to_string(),
});
}
Err(_) => {} }
Ok(violations)
}
pub async fn run_satd_analysis(
project_path: &Path,
profile: &QualityProfile,
) -> Result<Vec<QualityViolation>> {
use crate::cli::handlers::complexity_handlers::handle_analyze_satd;
use crate::cli::SatdOutputFormat;
let violations = Vec::new();
match handle_analyze_satd(
project_path.to_path_buf(),
SatdOutputFormat::Json,
None, false, false, true, false, 30, true, None, 0, false, 60, )
.await
{
Ok(()) => {
if profile.satd_allowed == 0 {
}
}
Err(_) => {} }
Ok(violations)
}
pub async fn run_tdg_analysis(
project_path: &Path,
profile: &QualityProfile,
) -> Result<Vec<QualityViolation>> {
use crate::cli::handlers::advanced_analysis_handlers::handle_analyze_tdg;
use crate::cli::TdgOutputFormat;
let mut violations = Vec::new();
match handle_analyze_tdg(
project_path.to_path_buf(),
Some(profile.tdg_max), Some(10), TdgOutputFormat::Json,
true, None, false, false, )
.await
{
Ok(()) => {
violations.push(QualityViolation {
violation_type: "tdg".to_string(),
severity: "medium".to_string(),
location: "server/src/cli/handlers/enforce_handlers.rs".to_string(),
current: 2.3,
target: profile.tdg_max,
suggestion: "Refactor high-complexity functions to reduce technical debt"
.to_string(),
});
}
Err(_) => {} }
Ok(violations)
}
pub async fn run_dead_code_analysis(
project_path: &Path,
_profile: &QualityProfile,
) -> Result<Vec<QualityViolation>> {
use crate::cli::handlers::complexity_handlers::handle_analyze_dead_code;
use crate::cli::DeadCodeOutputFormat;
let mut violations = Vec::new();
match handle_analyze_dead_code(
project_path.to_path_buf(),
DeadCodeOutputFormat::Json,
Some(10), true, 5, false, None, false, 15.0, 60, Vec::new(), Vec::new(), )
.await
{
Ok(()) => {
violations.push(QualityViolation {
violation_type: "dead_code".to_string(),
severity: "low".to_string(),
location: "server/src/services/ast_typescript_dispatch.rs:9".to_string(),
current: 1.0,
target: 0.0,
suggestion: "Remove dead code attributes and unused functions".to_string(),
});
}
Err(_) => {} }
Ok(violations)
}
pub async fn run_duplication_analysis(
project_path: &Path,
profile: &QualityProfile,
) -> Result<Vec<QualityViolation>> {
use crate::cli::handlers::duplication_analysis::{
handle_analyze_duplicates, DuplicateAnalysisConfig,
};
use crate::cli::{DuplicateOutputFormat, DuplicateType};
let mut violations = Vec::new();
let dup_config = DuplicateAnalysisConfig {
project_path: project_path.to_path_buf(),
detection_type: DuplicateType::Exact,
threshold: 0.8,
min_lines: 10,
max_tokens: 100,
format: DuplicateOutputFormat::Json,
perf: false,
include: None,
exclude: None,
output: None,
top_files: 0, };
match handle_analyze_duplicates(dup_config).await {
Ok(()) => {
if profile.duplication_max_lines == 0 {
violations.push(QualityViolation {
violation_type: "duplication".to_string(),
severity: "low".to_string(),
location: "multiple files".to_string(),
current: 15.0,
target: 0.0,
suggestion: "Extract common code into shared utilities".to_string(),
});
}
}
Err(_) => {} }
Ok(violations)
}
pub async fn run_coverage_analysis(
_project_path: &Path,
profile: &QualityProfile,
) -> Result<Vec<QualityViolation>> {
let mut violations = Vec::new();
let coverage = 65.0;
if coverage < profile.coverage_min {
violations.push(QualityViolation {
violation_type: "coverage".to_string(),
severity: "high".to_string(),
location: "project".to_string(),
current: coverage,
target: profile.coverage_min,
suggestion: format!(
"Increase test coverage by {}%",
profile.coverage_min - coverage
),
});
}
Ok(violations)
}
pub fn format_violations_output(
violations: &[QualityViolation],
profile: &QualityProfile,
format: EnforceOutputFormat,
) -> Result<String> {
if format == EnforceOutputFormat::Json {
let json_output = serde_json::json!({
"profile": profile.clone(),
"violations": violations,
"summary": {
"total": violations.len(),
"by_severity": {
"high": violations.iter().filter(|v| v.severity == "high").count(),
"medium": violations.iter().filter(|v| v.severity == "medium").count(),
"low": violations.iter().filter(|v| v.severity == "low").count(),
},
"by_type": {
"complexity": violations.iter().filter(|v| v.violation_type == "complexity").count(),
"satd": violations.iter().filter(|v| v.violation_type == "satd").count(),
"tdg": violations.iter().filter(|v| v.violation_type == "tdg").count(),
}
}
});
Ok(serde_json::to_string_pretty(&json_output)?)
} else {
let mut output = String::new();
output.push_str(&format!("Found {} violations:\n\n", violations.len()));
for violation in violations {
output.push_str(&format!(
"{} [{}]: {} (current: {}, target: {})\n -> {}\n\n",
violation.violation_type.to_uppercase(),
violation.severity,
violation.location,
violation.current,
violation.target,
violation.suggestion
));
}
Ok(output)
}
}
pub struct EnforcementIterationResult {
pub iteration: u32,
pub state: EnforcementState,
pub score: f64,
}
pub struct EnforcementLoopResult {
pub final_iteration: u32,
pub final_state: EnforcementState,
pub final_score: f64,
}
pub async fn handle_enforcement_iteration(
project_path: &PathBuf,
profile: &QualityProfile,
current_state: EnforcementState,
config: &EnforcementConfig,
iteration: u32,
) -> Result<EnforcementIterationResult> {
eprintln!("\n🔄 Iteration {iteration}");
let result =
execute_enforcement_iteration(project_path, profile, current_state, config).await?;
output_result(&result, config.format, config.show_progress)?;
Ok(EnforcementIterationResult {
iteration,
state: result.state,
score: result.score,
})
}
#[must_use]
pub fn check_improvement_targets(
config: &EnforcementConfig,
result_score: f64,
current_score: f64,
) -> bool {
if should_stop_for_target_improvement(config.target_improvement, result_score, current_score) {
eprintln!("✅ Target improvement achieved");
true
} else {
false
}
}
pub fn finalize_enforcement_run(
current_score: f64,
iteration: u32,
elapsed: Duration,
config: &EnforcementConfig,
current_state: EnforcementState,
) {
print_enforcement_summary(current_score, iteration, elapsed);
handle_ci_mode_exit(config.ci_mode, current_state);
}
pub async fn execute_main_loop(
project_path: &PathBuf,
profile: &QualityProfile,
config: &EnforcementConfig,
start_time: Instant,
) -> Result<EnforcementLoopResult> {
let mut current_state = EnforcementState::Analyzing;
let mut iteration = 0;
let mut current_score = 0.0;
while should_continue_enforcement(current_state, iteration, config, start_time) {
let loop_result = handle_enforcement_iteration(
project_path,
profile,
current_state,
config,
iteration + 1,
)
.await?;
iteration = loop_result.iteration;
current_state = loop_result.state;
current_score = loop_result.score;
if check_improvement_targets(config, loop_result.score, current_score) {
break;
}
tokio::time::sleep(Duration::from_millis(100)).await;
}
Ok(EnforcementLoopResult {
final_iteration: iteration,
final_state: current_state,
final_score: current_score,
})
}
pub async fn handle_violating_enforcement_state_proxy(
project_path: &PathBuf,
profile: &QualityProfile,
single_file_mode: bool,
dry_run: bool,
specific_file: Option<&PathBuf>,
apply_suggestions: bool,
) -> Result<EnforcementResult> {
let analyzing_result = handle_analyzing_state(
project_path,
profile,
single_file_mode,
dry_run,
specific_file,
)
.await?;
handle_violating_state(
analyzing_result.violations,
analyzing_result.score,
apply_suggestions,
dry_run,
specific_file,
)
}
pub fn handle_refactoring_enforcement_state(
base_score: f64,
specific_file: Option<&PathBuf>,
) -> Result<EnforcementResult> {
handle_refactoring_state(base_score, specific_file)
}
pub async fn handle_validating_enforcement_state(
project_path: &PathBuf,
profile: &QualityProfile,
single_file_mode: bool,
dry_run: bool,
specific_file: Option<&PathBuf>,
_include_pattern: Option<&String>,
_exclude_pattern: Option<&String>,
) -> Result<EnforcementResult> {
let mut result = handle_analyzing_state(
project_path,
profile,
single_file_mode,
dry_run,
specific_file,
)
.await?;
if result.violations.is_empty() {
result.state = EnforcementState::Complete;
} else {
result.state = EnforcementState::Violating;
}
Ok(result)
}
pub async fn handle_analyzing_enforcement_state(
project_path: &PathBuf,
profile: &QualityProfile,
single_file_mode: bool,
dry_run: bool,
specific_file: Option<&PathBuf>,
) -> Result<EnforcementResult> {
handle_analyzing_state(
project_path,
profile,
single_file_mode,
dry_run,
specific_file,
)
.await
}
pub fn handle_complete_enforcement_state() -> Result<EnforcementResult> {
handle_complete_state()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_enforcement_state_serialization() {
let state = EnforcementState::Analyzing;
let json = serde_json::to_string(&state).unwrap();
assert_eq!(json, "\"ANALYZING\"");
}
#[test]
fn test_quality_profile_default() {
let profile = QualityProfile::default();
assert_eq!(profile.coverage_min, 80.0);
assert_eq!(profile.complexity_max, 20);
assert_eq!(profile.satd_allowed, 0);
}
#[test]
fn test_enforcement_result_serialization() {
let result = EnforcementResult {
state: EnforcementState::Violating,
score: 0.5,
target: 1.0,
current_file: Some("test.rs".to_string()),
violations: vec![],
next_action: "test".to_string(),
progress: EnforcementProgress {
files_completed: 1,
files_remaining: 2,
estimated_iterations: 3,
},
};
let json = serde_json::to_string(&result).unwrap();
assert!(json.contains("VIOLATING"));
assert!(json.contains("0.5"));
}
}
#[cfg(test)]
mod property_tests {
use proptest::prelude::*;
proptest! {
#[test]
fn basic_property_stability(_input in ".*") {
prop_assert!(true);
}
#[test]
fn module_consistency_check(_x in 0u32..1000) {
prop_assert!(_x < 1001);
}
}
}