rumk 0.0.1

A fast linter for Makefiles
Documentation
use crate::diagnostic::Diagnostic;

pub fn apply_fixes(content: &str, diagnostics: &[Diagnostic]) -> String {
    let mut lines: Vec<String> = content.lines().map(|s| s.to_string()).collect();
    let mut fixable_diagnostics: Vec<_> = diagnostics
        .iter()
        .filter(|d| d.fixable && d.fix.is_some())
        .collect();

    fixable_diagnostics.sort_by(|a, b| b.line.cmp(&a.line).then_with(|| b.column.cmp(&a.column)));

    for diagnostic in fixable_diagnostics {
        if let Some(fix) = &diagnostic.fix {
            for edit in &fix.edits {
                apply_edit(&mut lines, edit);
            }
        }
    }

    lines.join("\n")
}

fn apply_edit(lines: &mut Vec<String>, edit: &crate::diagnostic::Edit) {
    if edit.start_line == 0 || edit.start_line > lines.len() {
        return;
    }

    let line_idx = edit.start_line - 1;

    if edit.start_line == edit.end_line {
        if let Some(line) = lines.get_mut(line_idx) {
            let start_col = edit.start_column.saturating_sub(1);
            let end_col = edit.end_column.saturating_sub(1).min(line.len());

            if start_col <= line.len() && start_col <= end_col {
                line.replace_range(start_col..end_col, &edit.replacement);
            }
        }
    } else {
        let start_col = edit.start_column.saturating_sub(1);
        let end_line_idx = (edit.end_line - 1).min(lines.len() - 1);
        let end_col = edit.end_column.saturating_sub(1);

        let prefix = lines[line_idx][..start_col.min(lines[line_idx].len())].to_string();
        let suffix = if end_line_idx < lines.len() {
            lines[end_line_idx][end_col.min(lines[end_line_idx].len())..].to_string()
        } else {
            String::new()
        };

        lines[line_idx] = format!("{}{}{}", prefix, edit.replacement, suffix);

        for _ in line_idx + 1..=end_line_idx.min(lines.len() - 1) {
            if line_idx + 1 < lines.len() {
                lines.remove(line_idx + 1);
            }
        }
    }
}