From 17ad9107f224fcee7db2e5bfce47f6afdd433105 Mon Sep 17 00:00:00 2001 From: granddaifuku Date: Wed, 9 Nov 2022 01:25:51 +0900 Subject: [PATCH 1/8] feat: remove suggestions' duplication --- src/checker/mod.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/checker/mod.rs b/src/checker/mod.rs index e257ebc9..c79f6768 100644 --- a/src/checker/mod.rs +++ b/src/checker/mod.rs @@ -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; @@ -110,9 +112,12 @@ impl Checker for Checkers { collective.extend(nlprule.check(origin, chunks)?); } - collective.sort(); + // Convert into a set to remove the duplicated suggestions + let set: HashSet = HashSet::from_iter(collective.iter().cloned()); + let mut suggestions: Vec> = Vec::from_iter(set); + suggestions.sort(); - Ok(collective) + Ok(suggestions) } } From b3e9ad68c1a365bc4a7ff520fb48332a0f6f78fa Mon Sep 17 00:00:00 2001 From: granddaifuku Date: Thu, 10 Nov 2022 00:13:28 +0900 Subject: [PATCH 2/8] fix: reduce one iteration --- src/checker/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/checker/mod.rs b/src/checker/mod.rs index c79f6768..7916bf34 100644 --- a/src/checker/mod.rs +++ b/src/checker/mod.rs @@ -104,7 +104,7 @@ impl Checker for Checkers { where 'a: 's, { - let mut collective = Vec::>::with_capacity(chunks.len()); + let mut collective = HashSet::>::new(); if let Some(ref hunspell) = self.hunspell { collective.extend(hunspell.check(origin, chunks)?); } @@ -112,9 +112,7 @@ impl Checker for Checkers { collective.extend(nlprule.check(origin, chunks)?); } - // Convert into a set to remove the duplicated suggestions - let set: HashSet = HashSet::from_iter(collective.iter().cloned()); - let mut suggestions: Vec> = Vec::from_iter(set); + let mut suggestions: Vec> = Vec::from_iter(collective); suggestions.sort(); Ok(suggestions) From 67b6d552ad7bba594521745cebb002693ef6312a Mon Sep 17 00:00:00 2001 From: granddaifuku Date: Mon, 21 Nov 2022 00:36:25 +0900 Subject: [PATCH 3/8] feat: method to detect the overlapping --- src/suggestion.rs | 96 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/src/suggestion.rs b/src/suggestion.rs index 1fbd3221..063a8568 100644 --- a/src/suggestion.rs +++ b/src/suggestion.rs @@ -315,6 +315,24 @@ pub struct Suggestion<'s> { pub description: Option, } +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.start.line != other.span.start.line { + return false; + } + + if self < other { + 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; @@ -994,4 +1012,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)); + } } From 6ede79de56c6f3e1c399002265e5245249a9da24 Mon Sep 17 00:00:00 2001 From: granddaifuku Date: Thu, 23 Feb 2023 01:04:05 +0900 Subject: [PATCH 4/8] feat: detect overlapped suggestions --- src/checker/mod.rs | 18 ++++++++++++++++++ src/suggestion.rs | 32 ++++++++++++++++---------------- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/checker/mod.rs b/src/checker/mod.rs index 7916bf34..e4ae4fcc 100644 --- a/src/checker/mod.rs +++ b/src/checker/mod.rs @@ -114,6 +114,24 @@ impl Checker for Checkers { let mut suggestions: Vec> = Vec::from_iter(collective); suggestions.sort(); + if suggestions.len() == 0 { + return Ok(suggestions); + } + + // Iterate through suggestions and identify overlapping ones. + let mut omitted: Vec = Vec::::new(); + let mut i: usize = 0; + while i < suggestions.len() - 1 as usize { + let cur = suggestions[i].clone(); + i += 1; + + while cur.is_overlapped(&suggestions[i]) { + let omit = suggestions.remove(i); + omitted.push(omit.chunk.clone()); + } + } + + // Re-run the checker and merge the results Ok(suggestions) } diff --git a/src/suggestion.rs b/src/suggestion.rs index 063a8568..077aa3f4 100644 --- a/src/suggestion.rs +++ b/src/suggestion.rs @@ -728,15 +728,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, ); @@ -779,15 +779,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, ); From 1e32c427ee189981915514725e7f3c99ae0cb49f Mon Sep 17 00:00:00 2001 From: granddaifuku Date: Thu, 23 Mar 2023 18:08:22 +0900 Subject: [PATCH 5/8] refactor: omitted suggestion logic using filter_map --- src/checker/mod.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/checker/mod.rs b/src/checker/mod.rs index e4ae4fcc..baa74d96 100644 --- a/src/checker/mod.rs +++ b/src/checker/mod.rs @@ -119,19 +119,17 @@ impl Checker for Checkers { } // Iterate through suggestions and identify overlapping ones. - let mut omitted: Vec = Vec::::new(); - let mut i: usize = 0; - while i < suggestions.len() - 1 as usize { - let cur = suggestions[i].clone(); - i += 1; - - while cur.is_overlapped(&suggestions[i]) { - let omit = suggestions.remove(i); - omitted.push(omit.chunk.clone()); - } - } - - // Re-run the checker and merge the results + let _omitted = suggestions + .iter() + .enumerate() + .filter_map(|(idx, cur)| { + if idx > 0 && cur.is_overlapped(&suggestions[idx - 1]) { + Some(cur.chunk.clone()) + } else { + None + } + }) + .collect::>(); Ok(suggestions) } From 935239be8c5582ac65f11891047846f4a439b20b Mon Sep 17 00:00:00 2001 From: granddaifuku Date: Tue, 28 Mar 2023 20:56:52 +0900 Subject: [PATCH 6/8] refactor: remove overlapping suggestions in the suggestions vector --- src/checker/mod.rs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/checker/mod.rs b/src/checker/mod.rs index baa74d96..1673c19b 100644 --- a/src/checker/mod.rs +++ b/src/checker/mod.rs @@ -119,17 +119,15 @@ impl Checker for Checkers { } // Iterate through suggestions and identify overlapping ones. - let _omitted = suggestions - .iter() - .enumerate() - .filter_map(|(idx, cur)| { - if idx > 0 && cur.is_overlapped(&suggestions[idx - 1]) { - Some(cur.chunk.clone()) + 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 } - }) - .collect::>(); + }, + )); Ok(suggestions) } From bc79fef1d916765646a41033e70afe89929ef7bb Mon Sep 17 00:00:00 2001 From: granddaifuku Date: Sat, 8 Apr 2023 19:51:01 +0900 Subject: [PATCH 7/8] fix: is_overlapped method to properly handle multi-line suggestions --- src/suggestion.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/suggestion.rs b/src/suggestion.rs index 077aa3f4..5ac171d3 100644 --- a/src/suggestion.rs +++ b/src/suggestion.rs @@ -321,7 +321,9 @@ impl<'s> Suggestion<'s> { if self.origin != other.origin { return false; } - if self.span.start.line != other.span.start.line { + + if self.span.end.line < other.span.start.line || other.span.end.line < self.span.start.line + { return false; } From c124c70cbebe5429750472f8720d3e6c8c6b7cf4 Mon Sep 17 00:00:00 2001 From: granddaifuku Date: Tue, 18 Apr 2023 01:29:25 +0900 Subject: [PATCH 8/8] fix: explicitly compare the spans instead of relying on the Ord implementation --- src/suggestion.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/suggestion.rs b/src/suggestion.rs index 5ac171d3..dbfe6b87 100644 --- a/src/suggestion.rs +++ b/src/suggestion.rs @@ -327,7 +327,10 @@ impl<'s> Suggestion<'s> { return false; } - if self < other { + 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