Skip to content

Commit

Permalink
feat(core): expanded CompoundWords to cover hyphenated cases
Browse files Browse the repository at this point in the history
  • Loading branch information
elijah-potter committed Jan 3, 2025
1 parent 6701c01 commit 39b41ae
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 6 deletions.
42 changes: 38 additions & 4 deletions harper-core/src/linting/compound_words.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ impl Linter for CompoundWords {
let mut lints = Vec::new();

let mut merged_word = CharString::new();
let mut potential_compounds = Vec::new();

for (a, w, b) in document.tokens().tuple_windows() {
if !a.kind.is_word() || !w.kind.is_whitespace() || !b.kind.is_word() {
Expand All @@ -43,17 +44,39 @@ impl Linter for CompoundWords {
continue;
}

potential_compounds.clear();

merged_word.clear();
merged_word.extend_from_slice(a_chars);
merged_word.extend_from_slice(b_chars);

// Check for closed compound words
if self.dict.contains_word(&merged_word) {
potential_compounds.push(merged_word.clone());
}

// Check for hyphenated compound words
merged_word.clear();
merged_word.extend_from_slice(a_chars);
merged_word.push('-');
merged_word.extend_from_slice(b_chars);

// Check for closed compound words
if self.dict.contains_word(&merged_word) {
potential_compounds.push(merged_word.clone());
}

if !potential_compounds.is_empty() {
lints.push(Lint {
span: Span::new(a.span.start, b.span.end),
lint_kind: LintKind::Spelling,
suggestions: vec![Suggestion::ReplaceWith(merged_word.to_vec())],
message: "These two words are often combined to form a closed compound word."
.to_owned(),
suggestions: potential_compounds
.drain(..)
.map(|v| Suggestion::ReplaceWith(v.to_vec()))
.collect(),
message:
"These two words are often combined to form a hyphenated compound word."
.to_owned(),
priority: 63,
});
}
Expand All @@ -69,7 +92,9 @@ impl Linter for CompoundWords {

#[cfg(test)]
mod tests {
use crate::linting::tests::assert_lint_count;
use crate::linting::tests::{
assert_lint_count, assert_suggestion_count, assert_suggestion_result,
};

use super::CompoundWords;

Expand Down Expand Up @@ -144,4 +169,13 @@ mod tests {
1,
);
}

#[test]
fn break_up() {
assert_suggestion_count(
"Like if you break up words you shouldn't.",
CompoundWords::default(),
2,
);
}
}
1 change: 0 additions & 1 deletion harper-core/src/linting/matcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ impl Matcher {
"The","hing" => "The thing",
"need","helps" => "need help",
"an","this" => "and this",
"break","up" => "break-up",
"case", "sensitive" => "case-sensitive",
"Tree", "sitter" => "Tree-sitter",
"all", "of", "the" => "all the",
Expand Down
13 changes: 12 additions & 1 deletion harper-core/src/linting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ pub trait Linter: Send + Sync {
#[cfg(test)]
mod tests {
use super::Linter;
use crate::Document;
use crate::{remove_overlaps, Document};

pub fn assert_lint_count(text: &str, mut linter: impl Linter, count: usize) {
let test = Document::new_markdown_curated(text);
Expand All @@ -83,6 +83,17 @@ mod tests {
assert_eq!(lints.len(), count);
}

/// Assert the total number of suggestions produced by a [`Linter`], spread across all produced
/// [`Lint`]s.
pub fn assert_suggestion_count(text: &str, mut linter: impl Linter, count: usize) {
let test = Document::new_markdown_curated(text);
let lints = linter.lint(&test);
assert_eq!(
lints.iter().map(|l| l.suggestions.len()).sum::<usize>(),
count
);
}

/// Runs a provided linter on text, applies the first suggestion from each
/// lint and asserts that the result is equal to a given value.
pub fn assert_suggestion_result(text: &str, mut linter: impl Linter, expected_result: &str) {
Expand Down

0 comments on commit 39b41ae

Please sign in to comment.