pub(crate) mod analyzer;
pub(crate) mod report;
use std::cmp::Reverse;
use std::error::Error;
use std::path::Path;
use crate::loc::language::LanguageSpec;
use crate::report_helpers;
use crate::walk::WalkConfig;
use analyzer::compute_mi;
use report::{FileMIMetrics, print_json, print_report, print_short, print_terse};
fn analyze_file(
path: &Path,
spec: &LanguageSpec,
exclude_tests: bool,
) -> Result<Option<FileMIMetrics>, Box<dyn Error>> {
let Some(of) = crate::mi::inputs(path, spec, exclude_tests)? else {
return Ok(None);
};
let metrics = compute_mi(of.volume, of.complexity, of.code_lines, of.comment_lines);
Ok(metrics.map(|metrics| FileMIMetrics {
path: path.to_path_buf(),
language: spec.name.to_string(),
metrics,
}))
}
pub fn run(
cfg: &WalkConfig<'_>,
output: crate::cli::OutputMode,
top: usize,
sort_by: &str,
) -> Result<(), Box<dyn Error>> {
let mut results = cfg.collect_analysis(analyze_file);
match sort_by {
"volume" => results.sort_by(|a, b| {
b.metrics
.halstead_volume
.total_cmp(&a.metrics.halstead_volume)
}),
"complexity" => {
results.sort_by_key(|r| Reverse(r.metrics.cyclomatic_complexity));
}
"loc" => results.sort_by_key(|r| Reverse(r.metrics.loc)),
_ => results.sort_by(|a, b| a.metrics.mi_score.total_cmp(&b.metrics.mi_score)),
}
report_helpers::output_results(
&mut results,
top,
output,
print_json,
print_report,
print_short,
print_terse,
)
}
#[cfg(test)]
#[path = "mod_test.rs"]
mod tests;