mod analyzer;
mod detection;
pub(crate) mod markers;
pub(crate) mod report;
use std::cmp::Reverse;
use std::error::Error;
use std::path::Path;
use crate::cli::OutputMode;
use crate::loc::counter::LineKind;
use crate::loc::language::LanguageSpec;
use crate::string_mask::code_view;
use crate::util::read_and_classify;
use crate::walk::WalkConfig;
use analyzer::analyze;
use markers::markers_for;
use report::{
FileCycomMetrics, print_codeclimate, print_github, print_json, print_per_function,
print_report, print_short, print_terse,
};
pub(crate) fn analyze_content(
lines: &[String],
kinds: &[LineKind],
spec: &LanguageSpec,
) -> Option<analyzer::FileComplexity> {
let cm = markers_for(spec.name)?;
let (lines, kinds) = code_view(lines, kinds, spec);
analyze(&lines, &kinds, cm)
}
pub(crate) fn analyze_file(
path: &Path,
spec: &LanguageSpec,
exclude_tests: bool,
) -> Result<Option<FileCycomMetrics>, Box<dyn Error>> {
let cm = match markers_for(spec.name) {
Some(m) => m,
None => return Ok(None),
};
let (lines, kinds) = match read_and_classify(path, spec, exclude_tests)? {
Some(v) => v,
None => return Ok(None),
};
let (lines, kinds) = code_view(&lines, &kinds, spec);
let fc = match analyze(&lines, &kinds, cm) {
Some(fc) => fc,
None => return Ok(None),
};
Ok(Some(FileCycomMetrics {
path: path.to_path_buf(),
language: spec.name.to_string(),
function_count: fc.functions.len(),
avg_complexity: fc.avg_complexity,
max_complexity: fc.max_complexity,
total_complexity: fc.total_complexity,
level: fc.level,
functions: fc.functions,
}))
}
pub fn run(
cfg: &WalkConfig<'_>,
output: OutputMode,
min_complexity: usize,
top: usize,
per_function: bool,
sort_by: &str,
) -> Result<(), Box<dyn Error>> {
let mut results = cfg.collect_analysis(analyze_file);
if min_complexity > 1 {
results.retain(|f| f.max_complexity >= min_complexity);
}
match sort_by {
"max" => results.sort_by_key(|r| Reverse(r.max_complexity)),
"avg" => results.sort_by(|a, b| {
b.avg_complexity
.partial_cmp(&a.avg_complexity)
.unwrap_or(std::cmp::Ordering::Equal)
}),
_ => results.sort_by_key(|r| Reverse(r.total_complexity)),
}
results.truncate(top);
match output {
OutputMode::Json => print_json(&results)?,
OutputMode::Short => print_short(&results),
OutputMode::Terse => print_terse(&results),
OutputMode::Github => print_github(&results, min_complexity),
OutputMode::Codeclimate => print_codeclimate(&results, min_complexity)?,
OutputMode::Table if per_function => print_per_function(&results, min_complexity),
OutputMode::Table => print_report(&results),
}
Ok(())
}
#[cfg(test)]
#[path = "mod_test.rs"]
mod tests;