pub(crate) mod analyzer;
pub(crate) mod report;
use std::error::Error;
use std::path::Path;
use crate::loc::counter::LineKind;
use crate::loc::language::LanguageSpec;
use crate::report_helpers;
use crate::util::read_and_classify;
use crate::walk::WalkConfig;
use analyzer::compute_mi;
use report::{FileMIMetrics, print_json, print_report};
fn analyze_file(path: &Path, spec: &LanguageSpec) -> Result<Option<FileMIMetrics>, Box<dyn Error>> {
let (lines, kinds) = match read_and_classify(path, spec)? {
Some(v) => v,
None => return Ok(None),
};
let code_lines = kinds.iter().filter(|k| **k == LineKind::Code).count();
let volume = match crate::hal::analyze_content(&lines, &kinds, spec) {
Some(h) => h.volume,
None => return Ok(None),
};
let complexity = match crate::cycom::analyze_content(&lines, &kinds, spec) {
Some(c) => c.total_complexity,
None => return Ok(None),
};
let metrics = match compute_mi(volume, complexity, code_lines) {
Some(m) => m,
None => return Ok(None),
};
Ok(Some(FileMIMetrics {
path: path.to_path_buf(),
language: spec.name.to_string(),
metrics,
}))
}
pub fn run(
cfg: &WalkConfig<'_>,
json: bool,
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(|a, b| {
b.metrics
.cyclomatic_complexity
.cmp(&a.metrics.cyclomatic_complexity)
});
}
"loc" => results.sort_by(|a, b| b.metrics.loc.cmp(&a.metrics.loc)),
_ => results.sort_by(|a, b| a.metrics.mi_score.total_cmp(&b.metrics.mi_score)),
}
report_helpers::output_results(&mut results, top, json, print_json, print_report)
}
#[cfg(test)]
#[path = "mod_test.rs"]
mod tests;