pub(crate) fn build_ignored_rules(
ignore_rules: Option<&str>,
exclude_rules: Option<&[String]>,
ignore_file_data: Option<&crate::linter::ignore_file::IgnoreFile>,
) -> HashSet<String> {
let mut rules = HashSet::new();
if let Some(ignore_str) = ignore_rules {
for code in ignore_str.split(',') {
let code = code.trim().to_uppercase();
if !code.is_empty() {
rules.insert(code);
}
}
}
if let Some(excludes) = exclude_rules {
for code in excludes {
let code = code.trim().to_uppercase();
if !code.is_empty() {
rules.insert(code);
}
}
}
if let Some(ignore) = ignore_file_data {
for code in ignore.ignored_rules() {
rules.insert(code);
}
}
rules
}
pub(crate) fn determine_min_severity(quiet: bool, level: LintLevel) -> crate::linter::Severity {
use crate::linter::Severity;
if quiet {
Severity::Warning } else {
match level {
LintLevel::Info => Severity::Info,
LintLevel::Warning => Severity::Warning,
LintLevel::Error => Severity::Error,
}
}
}
pub(crate) fn export_citl_if_requested(
input: &Path,
result_raw: &crate::linter::LintResult,
citl_export_path: Option<&Path>,
) {
use crate::linter::citl::CitlExport;
let Some(citl_path) = citl_export_path else {
return;
};
let export = CitlExport::from_lint_result(
input.to_str().unwrap_or("unknown"),
result_raw, );
if let Err(e) = export.write_to_file(citl_path) {
warn!(
"Failed to write CITL export to {}: {}",
citl_path.display(),
e
);
} else {
info!(
"CITL export written to {} ({} diagnostics)",
citl_path.display(),
export.summary.total
);
}
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn handle_lint_fixes(
input: &Path,
result_raw: &crate::linter::LintResult,
fix_assumptions: bool,
output: Option<&Path>,
file_is_makefile: bool,
format: LintFormat,
filter_diagnostics: &dyn Fn(crate::linter::LintResult) -> crate::linter::LintResult,
) -> Result<()> {
use crate::linter::autofix::{apply_fixes_to_file, FixOptions};
use crate::linter::output::write_results;
use crate::linter::rules::{lint_makefile, lint_shell};
let options = FixOptions {
create_backup: true,
dry_run: false,
backup_suffix: ".bak".to_string(),
apply_assumptions: fix_assumptions,
output_path: output.map(|p| p.to_path_buf()),
};
match apply_fixes_to_file(input, result_raw, &options) {
Ok(fix_result) => {
info!(
"Applied {} fix(es) to {}",
fix_result.fixes_applied,
input.display()
);
if let Some(backup_path) = &fix_result.backup_path {
info!("Backup created at {}", backup_path);
}
let source_after = fs::read_to_string(input).map_err(Error::Io)?;
let result_after_raw = if file_is_makefile {
lint_makefile(&source_after)
} else {
lint_shell(&source_after)
};
let result_after = filter_diagnostics(result_after_raw);
if result_after.diagnostics.is_empty() {
info!("All issues fixed!");
return Ok(());
}
info!("Remaining issues after auto-fix:");
let output_format = super::convert_lint_format(format);
let file_path = input.to_str().unwrap_or("unknown");
write_results(
&mut std::io::stdout(),
&result_after,
output_format,
file_path,
)
.map_err(|e| Error::Internal(format!("Failed to write lint results: {e}")))?;
Ok(())
}
Err(e) => Err(Error::Internal(format!("Failed to apply fixes: {e}"))),
}
}
pub(crate) fn output_lint_results(
result: &crate::linter::LintResult,
format: LintFormat,
input: &Path,
) -> Result<()> {
use crate::linter::output::write_results;
let output_format = super::convert_lint_format(format);
let file_path = input.to_str().unwrap_or("unknown");
write_results(&mut std::io::stdout(), result, output_format, file_path)
.map_err(|e| Error::Internal(format!("Failed to write lint results: {e}")))?;
if result.has_errors() {
std::process::exit(2);
} else if result.has_warnings() {
std::process::exit(1);
}
Ok(())
}
fn output_lint_results_no_exit(
result: &crate::linter::LintResult,
format: LintFormat,
input: &Path,
) -> Result<()> {
use crate::linter::output::write_results;
let output_format = super::convert_lint_format(format);
let file_path = input.to_str().unwrap_or("unknown");
write_results(&mut std::io::stdout(), result, output_format, file_path)
.map_err(|e| Error::Internal(format!("Failed to write lint results: {e}")))?;
Ok(())
}