#![doc = include_str!("../README.md")]
use std::time::Instant;
use anyhow::Result;
use bpaf::Bpaf;
use lintel_diagnostics::reporter::{CheckResult, CheckedFile, Reporter};
#[derive(Debug, Clone, Bpaf)]
#[bpaf(generate(check_args_inner))]
pub struct CheckArgs {
#[bpaf(long("fix"), switch)]
pub fix: bool,
#[bpaf(external(lintel_validate::validate_args))]
pub validate: lintel_validate::ValidateArgs,
}
pub fn check_args() -> impl bpaf::Parser<CheckArgs> {
check_args_inner()
}
pub async fn check(
args: &mut CheckArgs,
on_file_checked: impl FnMut(&CheckedFile),
) -> Result<CheckResult> {
let original_globs = args.validate.globs.clone();
let original_exclude = args.validate.exclude.clone();
lintel_validate::merge_config(&mut args.validate);
let lib_args = lintel_validate::validate::ValidateArgs::from(&args.validate);
let files = lintel_validate::validate::collect_files(&lib_args.globs, &lib_args.exclude)?;
let mut read_errors = Vec::new();
let file_contents = lintel_validate::validate::read_files(&files, &mut read_errors).await;
if args.fix {
let fixed = lintel_format::fix_format(&original_globs, &original_exclude)?;
if fixed > 0 {
eprintln!("Fixed formatting in {fixed} file(s).");
}
let mut result = lintel_validate::validate::run_with_contents(
&lib_args,
file_contents,
None,
on_file_checked,
)
.await?;
result.errors.extend(read_errors);
sort_errors(&mut result.errors);
Ok(result)
} else {
let format_errors = lintel_format::check_format_contents(
&file_contents,
&original_globs,
&original_exclude,
);
let mut result = lintel_validate::validate::run_with_contents(
&lib_args,
file_contents,
None,
on_file_checked,
)
.await?;
result.errors.extend(format_errors);
result.errors.extend(read_errors);
sort_errors(&mut result.errors);
Ok(result)
}
}
pub async fn run(args: &mut CheckArgs, reporter: &mut dyn Reporter) -> Result<bool> {
let start = Instant::now();
let result = check(args, |file| reporter.on_file_checked(file)).await?;
let had_errors = result.has_errors();
let elapsed = start.elapsed();
reporter.report(result, elapsed);
Ok(had_errors)
}
fn sort_errors(errors: &mut [lintel_diagnostics::LintelDiagnostic]) {
errors.sort_by(|a, b| {
a.path()
.cmp(b.path())
.then_with(|| a.offset().cmp(&b.offset()))
});
}