use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::Token;
use crate::expr::{Expr, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::patterns::UPOSSet;
use harper_brill::UPOS;
pub struct ThesesThese {
expr: SequenceExpr,
}
impl Default for ThesesThese {
fn default() -> Self {
let expr = SequenceExpr::default()
.t_aco("theses")
.t_ws()
.then(UPOSSet::new(&[UPOS::NOUN, UPOS::PROPN]));
Self { expr }
}
}
impl ExprLinter for ThesesThese {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
&self.expr
}
fn match_to_lint(&self, matched_tokens: &[Token], source: &[char]) -> Option<Lint> {
let theses_token = matched_tokens.first()?;
let content = theses_token.get_ch(source);
let suggestions = vec![Suggestion::replace_with_match_case_str("these", content)];
Some(Lint {
span: theses_token.span,
lint_kind: LintKind::Spelling,
suggestions,
message: "Did you mean `these`?".to_string(),
priority: 1,
})
}
fn description(&self) -> &'static str {
"Corrects the common misspelling of `these` as `theses`."
}
}
#[cfg(test)]
mod tests {
use crate::linting::tests::{assert_lint_count, assert_no_lints, assert_suggestion_result};
use super::ThesesThese;
#[test]
fn corrects_theses_scenes() {
assert_suggestion_result(
"Are theses scenes from a novel?",
ThesesThese::default(),
"Are these scenes from a novel?",
);
}
#[test]
fn corrects_theses_days() {
assert_suggestion_result(
"That's why the two countries look as they do theses days.",
ThesesThese::default(),
"That's why the two countries look as they do these days.",
);
}
#[test]
fn allows_correct_theses() {
assert_no_lints(
"There are universities that are dedicated just to this field, thousands of people doing theses on Picasso, for example.",
ThesesThese::default(),
);
}
#[test]
fn allows_theses_followed_by_verb() {
assert_no_lints(
"Theses are the times that try men's souls.",
ThesesThese::default(),
);
}
#[test]
fn works_with_capitalization() {
assert_suggestion_result(
"THESES BOOKS ARE GREAT.",
ThesesThese::default(),
"THESE BOOKS ARE GREAT.",
);
}
#[test]
fn works_with_mixed_capitalization() {
assert_suggestion_result(
"Theses Books Are My Favorite.",
ThesesThese::default(),
"These Books Are My Favorite.",
);
}
#[test]
fn simple_case() {
assert_suggestion_result(
"I like theses apples.",
ThesesThese::default(),
"I like these apples.",
);
}
#[test]
fn with_punctuation() {
assert_no_lints("Are theses, books good?", ThesesThese::default());
}
#[test]
fn in_the_middle_of_sentence() {
assert_suggestion_result(
"I saw theses movies yesterday.",
ThesesThese::default(),
"I saw these movies yesterday.",
);
}
#[test]
fn another_example() {
assert_lint_count("I have theses books.", ThesesThese::default(), 1);
}
#[test]
fn allows_band_name() {
assert_no_lints("Theses are a great band.", ThesesThese::default());
}
#[test]
fn does_not_correct_valid_theses() {
assert_no_lints(
"She wrote multiple theses on the topic.",
ThesesThese::default(),
);
}
}