Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: remove suggestions' duplication #286

Merged
merged 8 commits into from
Jul 18, 2023
23 changes: 20 additions & 3 deletions src/checker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ use crate::errors::*;
mod cached;
use self::cached::Cached;

use std::collections::HashSet;

mod tokenize;
pub(crate) use self::hunspell::HunspellChecker;
pub(crate) use self::nlprules::NlpRulesChecker;
Expand Down Expand Up @@ -102,17 +104,32 @@ impl Checker for Checkers {
where
'a: 's,
{
let mut collective = Vec::<Suggestion<'s>>::with_capacity(chunks.len());
let mut collective = HashSet::<Suggestion<'s>>::new();
if let Some(ref hunspell) = self.hunspell {
collective.extend(hunspell.check(origin, chunks)?);
}
if let Some(ref nlprule) = self.nlprules {
collective.extend(nlprule.check(origin, chunks)?);
}

collective.sort();
let mut suggestions: Vec<Suggestion<'s>> = Vec::from_iter(collective);
suggestions.sort();
drahnr marked this conversation as resolved.
Show resolved Hide resolved
if suggestions.len() == 0 {
return Ok(suggestions);
}

// Iterate through suggestions and identify overlapping ones.
let suggestions = Vec::from_iter(suggestions.clone().into_iter().enumerate().filter_map(
|(idx, cur)| {
if idx == 0 || !cur.is_overlapped(&suggestions[idx - 1]) {
Some(cur)
} else {
None
}
},
));

Ok(collective)
Ok(suggestions)
}
}

Expand Down
133 changes: 117 additions & 16 deletions src/suggestion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,29 @@ pub struct Suggestion<'s> {
pub description: Option<String>,
}

impl<'s> Suggestion<'s> {
/// Determine if there is overlap.
pub fn is_overlapped(&self, other: &Self) -> bool {
if self.origin != other.origin {
return false;
}

if self.span.end.line < other.span.start.line || other.span.end.line < self.span.start.line
{
return false;
}

if self.span.start.line < other.span.start.line
|| (self.span.start.line == other.span.start.line
&& self.span.start.column < other.span.start.column)
{
self.span.end.column > other.span.start.column
} else {
self.span.start.column < other.span.end.column
}
}
}

impl<'s> fmt::Display for Suggestion<'s> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
use console::Style;
Expand Down Expand Up @@ -710,15 +733,15 @@ mod tests {
let chunk = CheckableChunk::from_str(
CONTENT,
indexmap::indexmap! { 0..18 => Span {
start: LineColumn {
line: 1,
column: 0,
},
end: LineColumn {
line: 1,
column: 17,
}
start: LineColumn {
line: 1,
column: 0,
},
end: LineColumn {
line: 1,
column: 17,
}
}
},
CommentVariant::TripleSlash,
);
Expand Down Expand Up @@ -761,15 +784,15 @@ mod tests {
let chunk = CheckableChunk::from_str(
CONTENT,
indexmap::indexmap! { 0..18 => Span {
start: LineColumn {
line: 1,
column: 0,
},
end: LineColumn {
line: 1,
column: 17,
}
start: LineColumn {
line: 1,
column: 0,
},
end: LineColumn {
line: 1,
column: 17,
}
}
},
CommentVariant::TripleSlash,
);
Expand Down Expand Up @@ -994,4 +1017,82 @@ mod tests {
log::info!("fmt debug=\n{:?}\n<", suggestion);
log::info!("fmt display=\n{}\n<", suggestion);
}

#[test]
fn overlapped() {
let chunk = CheckableChunk::from_str(
r#"0
2345
7@n"#,
indexmap::indexmap! { 0..10 => Span {
start : LineColumn {
line: 7usize,
column: 8usize,
},
end : LineColumn {
line: 9usize,
column: 4usize,
}
} },
CommentVariant::TripleSlash,
);
let suggestion = Suggestion {
detector: Detector::Dummy,
origin: ContentOrigin::TestEntityRust,
chunk: &chunk,
span: Span {
start: LineColumn {
line: 8usize,
column: 1,
},
end: LineColumn {
line: 8usize,
column: 3,
},
},
range: 2..6,
replacements: vec!["whocares".to_owned()],
description: None,
};
let overlapped_smaller_suggestion = Suggestion {
detector: Detector::Dummy,
origin: ContentOrigin::TestEntityRust,
chunk: &chunk,
span: Span {
start: LineColumn {
line: 8usize,
column: 0,
},
end: LineColumn {
line: 8usize,
column: 2,
},
},
range: 2..6,
replacements: vec!["whocares".to_owned()],
description: None,
};

let overlapped_larger_suggestion = Suggestion {
detector: Detector::Dummy,
origin: ContentOrigin::TestEntityRust,
chunk: &chunk,
span: Span {
start: LineColumn {
line: 8usize,
column: 2,
},
end: LineColumn {
line: 8usize,
column: 3,
},
},
range: 2..6,
replacements: vec!["whocares".to_owned()],
description: None,
};

assert!(suggestion.is_overlapped(&overlapped_smaller_suggestion));
assert!(suggestion.is_overlapped(&overlapped_larger_suggestion));
}
}