use std::cmp::Reverse;
use std::collections::BTreeMap;
use std::fs;
use std::path::Path;
use anyhow::Context;
use anyhow::Result;
use super::TaggedFix;
use super::ValidatedFixSet;
use crate::reporting::AppliedFixCounts;
pub(in crate::fixes) fn apply_fixes(fixes: &ValidatedFixSet) -> Result<AppliedFixCounts> {
let mut by_file: BTreeMap<&Path, Vec<&TaggedFix>> = BTreeMap::new();
for tagged in fixes.tagged() {
by_file
.entry(tagged.fix.path.as_path())
.or_default()
.push(tagged);
}
let mut applied = AppliedFixCounts::default();
for (path, mut file_fixes) in by_file {
let mut text = fs::read_to_string(path)
.with_context(|| format!("failed to read {}", path.display()))?;
file_fixes.sort_by_key(|tagged| Reverse((tagged.fix.start, tagged.fix.end)));
for tagged in file_fixes {
let fix = &tagged.fix;
if fix.end <= text.len() && fix.start <= fix.end {
text.replace_range(fix.start..fix.end, &fix.replacement);
if let Some(fix_kind) = tagged.fix_kind {
applied.record(fix_kind);
}
}
}
fs::write(path, text).with_context(|| format!("failed to write {}", path.display()))?;
}
Ok(applied)
}