use crate::findings::Suppression;
pub(crate) trait DrySuppressible {
fn set_suppressed(&mut self, val: bool);
fn entry_locations(&self) -> Vec<(&str, usize)>;
}
impl DrySuppressible for crate::dry::functions::DuplicateGroup {
fn set_suppressed(&mut self, val: bool) {
self.suppressed = val;
}
fn entry_locations(&self) -> Vec<(&str, usize)> {
self.entries
.iter()
.map(|e| (e.file.as_str(), e.line))
.collect()
}
}
impl DrySuppressible for crate::dry::match_patterns::RepeatedMatchGroup {
fn set_suppressed(&mut self, val: bool) {
self.suppressed = val;
}
fn entry_locations(&self) -> Vec<(&str, usize)> {
self.entries
.iter()
.map(|e| (e.file.as_str(), e.line))
.collect()
}
}
impl DrySuppressible for crate::dry::fragments::FragmentGroup {
fn set_suppressed(&mut self, val: bool) {
self.suppressed = val;
}
fn entry_locations(&self) -> Vec<(&str, usize)> {
self.entries
.iter()
.map(|e| (e.file.as_str(), e.start_line))
.collect()
}
}
impl DrySuppressible for crate::dry::boilerplate::BoilerplateFind {
fn set_suppressed(&mut self, val: bool) {
self.suppressed = val;
}
fn entry_locations(&self) -> Vec<(&str, usize)> {
vec![(self.file.as_str(), self.line)]
}
}
pub(crate) fn mark_dry_suppressions<T: DrySuppressible>(
groups: &mut [T],
suppression_lines: &std::collections::HashMap<String, Vec<Suppression>>,
) {
let dry_dim = crate::findings::Dimension::Dry;
groups.iter_mut().for_each(|g| {
let suppressed = g.entry_locations().iter().any(|(file, line)| {
suppression_lines
.get(*file)
.map(|sups| {
sups.iter().any(|sup| {
crate::findings::is_within_window(sup.line, *line) && sup.covers(dry_dim)
})
})
.unwrap_or(false)
});
g.set_suppressed(suppressed);
});
}
pub(super) fn mark_inverse_suppressions(
groups: &mut [crate::dry::functions::DuplicateGroup],
inverse_lines: &std::collections::HashMap<String, Vec<(usize, String)>>,
) {
let window = crate::findings::ANNOTATION_WINDOW;
groups.iter_mut().filter(|g| !g.suppressed).for_each(|g| {
g.suppressed = g.entries.iter().any(|entry| {
inverse_lines
.get(&entry.file)
.map(|inv| {
inv.iter().any(|(line, target)| {
let in_window = *line <= entry.line && entry.line - line <= window;
in_window
&& g.entries.iter().any(|other| {
other.name == *target || other.qualified_name == *target
})
})
})
.unwrap_or(false)
});
});
}