use alloc::collections::BTreeMap;
use alloc::collections::BTreeSet;
use alloc::vec::Vec;
use vize_l0::{Span, String};
use super::args_text;
use super::corpus::CorpusRemark;
use crate::pass::observer::RemarkKind;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BacklogItem {
pub stage: String,
pub pass: String,
pub name: String,
pub reason: String,
pub hits: usize,
pub files: usize,
pub example: (String, Span),
}
#[must_use]
pub fn mine_missed(entries: &[CorpusRemark]) -> Vec<BacklogItem> {
type Key = (String, String, String, String);
type Group<'e> = (usize, BTreeSet<&'e str>, (String, Span));
let mut groups: BTreeMap<Key, Group<'_>> = BTreeMap::new();
for entry in entries {
let remark = &entry.remark;
if remark.kind != RemarkKind::Missed {
continue;
}
let reason = args_text(remark.args.get(1..).unwrap_or(&[]));
let key = (
remark.stage.clone(),
remark.pass.clone(),
remark.name.clone(),
reason,
);
let group = groups
.entry(key)
.or_insert_with(|| (0, BTreeSet::new(), (entry.path.clone(), remark.span)));
group.0 += 1;
group.1.insert(entry.path.as_str());
}
let mut items: Vec<BacklogItem> = groups
.into_iter()
.map(
|((stage, pass, name, reason), (hits, files, example))| BacklogItem {
stage,
pass,
name,
reason,
hits,
files: files.len(),
example,
},
)
.collect();
items.sort_by_key(|item| core::cmp::Reverse(item.hits));
items
}