#![cfg_attr(coverage_nightly, coverage(off))]
use super::assessment::assess_project;
use super::config::EnforcementConfig;
use super::output::{
emit_report, format_violations_output, handle_ci_mode_exit, output_result,
print_enforcement_summary,
};
use super::states::{
handle_analyzing_state, handle_refactoring_pass, handle_validating_enforcement_state,
handle_violating_enforcement_state_proxy,
};
use super::types::{
EnforcementIterationResult, EnforcementLoopResult, EnforcementResult, EnforcementState,
QualityProfile,
};
use crate::cli::colors as c;
use crate::cli::EnforceOutputFormat;
use anyhow::Result;
use std::path::{Path, PathBuf};
use std::time::{Duration, Instant};
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub async fn handle_special_modes(
list_violations: bool,
validate_only: bool,
project_path: &PathBuf,
profile: &QualityProfile,
format: EnforceOutputFormat,
ci_mode: bool,
specific_file: Option<&PathBuf>,
output: Option<&Path>,
include_pattern: Option<&String>,
exclude_pattern: Option<&String>,
) -> Result<Option<Result<()>>> {
if list_violations {
return Ok(Some(
list_all_violations(
project_path,
profile,
format,
ci_mode,
specific_file,
output,
include_pattern,
exclude_pattern,
)
.await,
));
}
if validate_only {
return Ok(Some(
validate_current_state(
project_path,
profile,
format,
ci_mode,
specific_file,
output,
include_pattern,
exclude_pattern,
)
.await,
));
}
Ok(None)
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub async fn run_main_enforcement_loop(
project_path: &PathBuf,
profile: &QualityProfile,
config: EnforcementConfig,
output: Option<&Path>,
) -> Result<()> {
let start_time = Instant::now();
let loop_result = execute_main_loop(project_path, profile, &config, start_time, output).await?;
finalize_enforcement_run(
loop_result.final_score,
loop_result.final_iteration,
start_time.elapsed(),
&config,
loop_result.final_state,
);
Ok(())
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub 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!("{}", c::warn("Time limit reached"));
return false;
}
}
true
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub 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
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
pub 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
}
}
#[must_use]
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
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!("{}", c::pass("Target improvement achieved"));
true
} else {
false
}
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "check_compliance")]
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);
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub async fn handle_enforcement_iteration(
project_path: &PathBuf,
profile: &QualityProfile,
current_state: EnforcementState,
config: &EnforcementConfig,
iteration: u32,
output: Option<&Path>,
) -> Result<EnforcementIterationResult> {
crate::status_eprintln!(
"\n{} {}",
c::label("Iteration"),
c::number(&iteration.to_string())
);
let result =
execute_enforcement_iteration(project_path, profile, current_state, config).await?;
output_result(&result, config.format, config.show_progress, output)?;
Ok(EnforcementIterationResult {
iteration,
state: result.state,
score: result.score,
})
}
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub async fn execute_main_loop(
project_path: &PathBuf,
profile: &QualityProfile,
config: &EnforcementConfig,
start_time: Instant,
output: Option<&Path>,
) -> Result<EnforcementLoopResult> {
let mut current_state = EnforcementState::Analyzing;
let mut iteration = 0;
let mut current_score = 0.0;
let mut seen: Vec<(EnforcementState, f64)> = Vec::new();
while should_continue_enforcement(current_state, iteration, config, start_time) {
let loop_result = handle_enforcement_iteration(
project_path,
profile,
current_state,
config,
iteration + 1,
output,
)
.await?;
iteration = loop_result.iteration;
let score_before = current_score;
current_state = loop_result.state;
current_score = loop_result.score;
if check_improvement_targets(config, loop_result.score, score_before) {
break;
}
if seen.iter().any(|(state, score)| {
*state == loop_result.state && (score - loop_result.score).abs() < f64::EPSILON
}) {
eprintln!(
"{}",
c::warn(&format!(
"no progress after {iteration} iterations ({:?} at {:.2} has already been reported); stopping",
loop_result.state, loop_result.score
))
);
break;
}
seen.push((loop_result.state, loop_result.score));
tokio::time::sleep(Duration::from_millis(100)).await;
}
Ok(EnforcementLoopResult {
final_iteration: iteration,
final_state: current_state,
final_score: current_score,
})
}
#[allow(clippy::too_many_arguments)]
#[provable_contracts_macros::contract("pmat-core.yaml", equation = "path_exists")]
pub 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,
include_pattern,
exclude_pattern,
)
.await
}
EnforcementState::Violating => {
handle_violating_enforcement_state_proxy(
project_path,
profile,
single_file_mode,
dry_run,
specific_file,
apply_suggestions,
include_pattern,
exclude_pattern,
)
.await
}
EnforcementState::Refactoring => {
handle_refactoring_pass(
project_path,
profile,
single_file_mode,
dry_run,
specific_file,
include_pattern,
exclude_pattern,
)
.await
}
EnforcementState::Validating => {
handle_validating_enforcement_state(
project_path,
profile,
single_file_mode,
dry_run,
specific_file,
include_pattern,
exclude_pattern,
)
.await
}
EnforcementState::Complete => {
handle_analyzing_state(
project_path,
profile,
single_file_mode,
dry_run,
specific_file,
include_pattern,
exclude_pattern,
)
.await
}
}
}
async fn list_all_violations(
project_path: &Path,
profile: &QualityProfile,
format: EnforceOutputFormat,
ci_mode: bool,
specific_file: Option<&PathBuf>,
output: Option<&Path>,
include_pattern: Option<&String>,
exclude_pattern: Option<&String>,
) -> Result<()> {
crate::status_eprintln!("{}", c::header("Listing all quality violations..."));
let assessment = assess_project(
project_path,
profile,
specific_file.map(PathBuf::as_path),
include_pattern,
exclude_pattern,
)
.await?;
crate::status_eprintln!(
"\n{} {} violations ({}{}/{} dimensions measured)",
c::label("Found"),
c::number(&assessment.violations.len().to_string()),
c::DIM,
assessment.measured_phases,
assessment.total_phases
);
if !crate::cli::progress::quiet_mode_enabled() {
eprint!("{}", c::RESET);
}
let formatted_output = format_violations_output(&assessment.violations, profile, format)?;
emit_report(&formatted_output, output)?;
handle_ci_mode_exit(ci_mode, assessment.verdict_state());
Ok(())
}
async fn validate_current_state(
project_path: &PathBuf,
profile: &QualityProfile,
format: EnforceOutputFormat,
ci_mode: bool,
specific_file: Option<&PathBuf>,
output: Option<&Path>,
include_pattern: Option<&String>,
exclude_pattern: Option<&String>,
) -> Result<()> {
crate::status_eprintln!("{}", c::label("Validating current quality state..."));
let result = run_enforcement_step(
project_path,
profile,
EnforcementState::Analyzing,
specific_file.is_some(), true, false, specific_file,
include_pattern,
exclude_pattern,
)
.await?;
let passes = result.state == EnforcementState::Complete;
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: result.progress,
};
output_result(&validation_result, format, false, output)?;
if ci_mode && !passes {
eprintln!("\n{}", c::fail("Quality validation failed!"));
eprintln!(
" {} {}{:.2}{}/{}{:.2}{}",
c::label("Score:"),
c::BOLD_WHITE,
result.score,
c::RESET,
c::DIM,
result.target,
c::RESET
);
eprintln!(
" {} {}",
c::label("Violations:"),
c::number(&validation_result.violations.len().to_string())
);
std::process::exit(1);
}
Ok(())
}