axbuild 0.4.14

An OS build lib toolkit used by arceos
Documentation
use std::{collections::HashMap, path::Path};

use super::check::ClippyCheck;

#[derive(Debug, Clone, PartialEq, Eq)]
pub(super) struct PackageRunReport {
    pub(super) package: String,
    pub(super) total_checks: usize,
    pub(super) failed_checks: Vec<String>,
}

impl PackageRunReport {
    fn new(package: String) -> Self {
        Self {
            package,
            total_checks: 0,
            failed_checks: Vec::new(),
        }
    }

    fn passed(&self) -> bool {
        self.failed_checks.is_empty()
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub(super) struct ClippyRunReport {
    pub(super) total_checks: usize,
    pub(super) passed_checks: usize,
    pub(super) packages: Vec<PackageRunReport>,
}

impl ClippyRunReport {
    pub(super) fn passed_packages(&self) -> Vec<String> {
        self.packages
            .iter()
            .filter(|package| package.passed())
            .map(|package| package.package.clone())
            .collect()
    }

    pub(super) fn failed_packages(&self) -> Vec<String> {
        self.packages
            .iter()
            .filter(|package| !package.passed())
            .map(|package| package.package.clone())
            .collect()
    }
}

pub(super) fn planned_clippy_report(checks: &[ClippyCheck]) -> ClippyRunReport {
    let mut packages = Vec::new();
    let mut package_indexes = HashMap::new();

    for check in checks {
        if package_indexes.contains_key(check.package.as_str()) {
            continue;
        }
        let index = packages.len();
        packages.push(PackageRunReport::new(check.package.clone()));
        package_indexes.insert(check.package.clone(), index);
    }

    ClippyRunReport {
        total_checks: checks.len(),
        passed_checks: 0,
        packages,
    }
}

pub(super) fn print_clippy_check_plan(
    workspace_root: &Path,
    index: usize,
    total: usize,
    check: &ClippyCheck,
) {
    let args = check.cargo_args();
    println!("[{}/{}] {}", index + 1, total, check.label());
    if check.env.is_empty() {
        println!(
            "          cd {} && cargo {}",
            workspace_root.display(),
            args.join(" ")
        );
    } else {
        println!(
            "          cd {} && {} cargo {}",
            workspace_root.display(),
            check.env_prefix(),
            args.join(" ")
        );
    }
}

pub(super) fn print_report_summary(report: &ClippyRunReport) {
    println!(
        "clippy summary: {} package(s), {} check(s), {} package(s) passed, {} package(s) failed",
        report.packages.len(),
        report.total_checks,
        report.passed_packages().len(),
        report.failed_packages().len()
    );
    println!(
        "passed checks: {}, failed checks: {}",
        report.passed_checks,
        report.total_checks.saturating_sub(report.passed_checks)
    );

    let failed_packages = report.failed_packages();
    if !failed_packages.is_empty() {
        eprintln!("failed packages: {}", failed_packages.join(", "));
        for package in report.packages.iter().filter(|package| !package.passed()) {
            eprintln!(
                "  {} failed {} check(s): {}",
                package.package,
                package.failed_checks.len(),
                package.failed_checks.join(", ")
            );
        }
    }
}