use anyhow::Result;
const RAYON_STACK_SIZE: usize = 8 * 1024 * 1024;
pub const MAIN_STACK_SIZE: usize = 16 * 1024 * 1024;
pub fn configure_thread_pool(jobs: usize) {
let mut builder = rayon::ThreadPoolBuilder::new().stack_size(RAYON_STACK_SIZE);
if jobs > 0 {
builder = builder.num_threads(jobs);
}
if let Err(e) = builder.build_global() {
eprintln!("Note: Thread pool already configured: {}", e);
}
}
pub fn get_worker_count(jobs: usize) -> usize {
if jobs == 0 {
std::thread::available_parallelism()
.map(|n| n.get())
.unwrap_or(4)
} else {
jobs
}
}
fn is_automation_mode_from_values(automation: Option<&str>, validation: Option<&str>) -> bool {
let is_true = |opt: Option<&str>| opt.is_some_and(|v| v.eq_ignore_ascii_case("true"));
is_true(automation) || is_true(validation)
}
pub fn is_automation_mode() -> bool {
is_automation_mode_from_values(
std::env::var("PRODIGY_AUTOMATION").ok().as_deref(),
std::env::var("PRODIGY_VALIDATION").ok().as_deref(),
)
}
pub fn apply_environment_setup(no_context_aware: bool) -> Result<()> {
if !no_context_aware {
std::env::set_var("DEBTMAP_CONTEXT_AWARE", "true");
}
Ok(())
}
pub fn print_metrics_explanation() {
println!("\n=== Debtmap Metrics Reference ===\n");
println!("## Metric Categories (Spec 118)\n");
println!("Debtmap distinguishes between two types of metrics:\n");
println!("### Measured Metrics");
println!("These metrics are directly computed from the AST (Abstract Syntax Tree):");
println!(" - cyclomatic_complexity: Count of decision points (if, match, while, etc.)");
println!(" - cognitive_complexity: Weighted measure of code understandability");
println!(" - nesting_depth: Maximum levels of nested control structures");
println!(" - loc: Lines of code in the function");
println!(" - parameter_count: Number of function parameters\n");
println!("### Estimated Metrics");
println!("These metrics are heuristic estimates, not precise AST measurements:");
println!(" - est_branches: Estimated execution paths (formula-based approximation)");
println!(" Formula: max(nesting_depth, 1) x cyclomatic_complexity / 3");
println!(" Purpose: Estimate test cases needed for branch coverage");
println!(" Note: This is an ESTIMATE, not a count from the AST\n");
println!("## Why the Distinction Matters\n");
println!("- Measured metrics: Precise, repeatable, suitable for thresholds");
println!("- Estimated metrics: Approximate, useful for prioritization and heuristics");
println!("- Use cyclomatic_complexity for code quality gates");
println!("- Use est_branches for estimating testing effort\n");
println!("## Terminology Change (Spec 118)\n");
println!("Previously called 'branches', now renamed to 'est_branches' to:");
println!(" 1. Make it clear this is an estimate, not a measured value");
println!(" 2. Avoid confusion with cyclomatic complexity (actual branches)");
println!(" 3. Set accurate expectations for users\n");
println!("## Example Usage\n");
println!(" debtmap analyze . --threshold-complexity 15 # Use measured cyclomatic");
println!(
" debtmap analyze . --top 10 # Uses est_branches for prioritization"
);
println!(" debtmap analyze . --lcov coverage.info # Coverage vs complexity\n");
println!("For more details, see: https://docs.debtmap.dev/metrics-reference\n");
}
pub fn show_config_sources() -> Result<()> {
use crate::config::multi_source::{display_config_sources, load_multi_source_config};
match load_multi_source_config() {
Ok(traced) => {
display_config_sources(&traced);
Ok(())
}
Err(errors) => {
eprintln!("Error loading configuration:");
for error in errors {
eprintln!(" - {}", error);
}
Err(anyhow::anyhow!("Configuration loading failed"))
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_get_worker_count_explicit() {
assert_eq!(get_worker_count(4), 4);
assert_eq!(get_worker_count(8), 8);
}
#[test]
fn test_get_worker_count_auto() {
let count = get_worker_count(0);
assert!(count > 0);
}
#[test]
fn test_automation_mode_with_automation_true() {
assert!(is_automation_mode_from_values(Some("true"), None));
assert!(is_automation_mode_from_values(Some("TRUE"), None));
assert!(is_automation_mode_from_values(Some("True"), None));
}
#[test]
fn test_automation_mode_with_validation_true() {
assert!(is_automation_mode_from_values(None, Some("true")));
assert!(is_automation_mode_from_values(None, Some("TRUE")));
assert!(is_automation_mode_from_values(None, Some("True")));
}
#[test]
fn test_automation_mode_both_unset() {
assert!(!is_automation_mode_from_values(None, None));
}
#[test]
fn test_automation_mode_non_true_values() {
assert!(!is_automation_mode_from_values(Some("false"), None));
assert!(!is_automation_mode_from_values(Some("1"), None));
assert!(!is_automation_mode_from_values(Some(""), None));
assert!(!is_automation_mode_from_values(None, Some("false")));
}
#[test]
fn test_automation_mode_both_true() {
assert!(is_automation_mode_from_values(Some("true"), Some("true")));
}
}