use crate::engine::{CompiledPolicy, Hit};
use crate::extract::{Doc, RegionKind};
use crate::input::Prepared;
use crate::Config;
pub const HANDLED: &[&str] = &["SLOP-H001", "SLOP-H002", "SLOP-H003"];
pub fn evaluate(
cp: &CompiledPolicy,
prepared: &Prepared,
doc: &Doc,
config: &Config,
hits: &mut Vec<Hit>,
) {
if let Some(idx) = super::active(cp, config, "SLOP-H002") {
let rule = &cp.pkg.rules[idx];
let flag_pct = super::param_i64(rule, "flag_excluded_pct").unwrap_or(40) as usize;
let total = prepared.text.len();
let prose: usize = doc
.regions
.iter()
.filter(|r| r.kind == RegionKind::Prose)
.map(|r| r.range.len())
.sum();
if total > 0 && (total - prose) * 100 >= flag_pct * total {
hits.push(Hit::new(idx, 0..total.min(1)));
}
}
if let Some(idx) = super::active(cp, config, "SLOP-H003") {
if prepared.mixed_line_endings || prepared.bom_stripped {
hits.push(Hit::new(idx, 0..prepared.text.len().min(1)));
}
'scan: for (range, _) in &doc.prose_regions {
let slice = &prepared.text[range.clone()];
let mut i = 0usize;
while i < slice.len() {
let ch = slice[i..].chars().next().unwrap_or('\u{FFFD}');
let l = ch.len_utf8();
if crate::views::confusable_latin(ch).is_some()
&& crate::views::token_mixes_latin(slice, i, l)
{
hits.push(Hit::new(idx, range.start + i..range.start + i + l));
break 'scan;
}
i += l;
}
}
}
}