#![forbid(unsafe_code)]
mod diagnostic;
mod regex_util;
mod rule;
mod rule_set;
pub mod stdlib;
mod suppression;
use std::ops::Range;
use mdwright_document::Document;
pub use diagnostic::{DOCS_URL_DEFAULT, Diagnostic, Fix, Severity, Snippet, docs_url, rule_doc_url};
pub use rule::LintRule;
pub use rule_set::{DuplicateRuleName, RuleSet};
#[derive(Copy, Clone, Debug)]
pub struct LintOptions {
pub respect_suppressions: bool,
}
impl Default for LintOptions {
fn default() -> Self {
Self {
respect_suppressions: true,
}
}
}
#[must_use]
pub fn apply_safe_fixes(doc: &Document, diags: &[Diagnostic]) -> (String, usize) {
let mut edits: Vec<(Range<usize>, &str)> = diags
.iter()
.filter_map(|d| {
let fix = d.fix.as_ref().filter(|f| f.safe)?;
let orig = doc.canonical_to_original_range(d.span.start..d.span.end);
Some((orig, fix.replacement.as_str()))
})
.collect();
edits.sort_by_key(|e| std::cmp::Reverse(e.0.start));
let mut out = doc.original_source().to_owned();
let mut applied = 0usize;
let mut last_start = usize::MAX;
for (range, replacement) in edits {
if range.end > last_start {
continue;
}
out.replace_range(range.clone(), replacement);
last_start = range.start;
applied = applied.saturating_add(1);
}
(out, applied)
}