harper-core 2.0.0

The language checker for developers.
Documentation
use crate::linting::expr_linter::Chunk;
use crate::{
    Token,
    expr::SequenceExpr,
    linting::{ExprLinter, Lint, LintKind, Suggestion},
    patterns::WordSet,
};

pub struct HopeYoure {
    expr: SequenceExpr,
}

impl Default for HopeYoure {
    fn default() -> Self {
        let loc = WordSet::new(&["here", "there"]);

        let prep = SequenceExpr::default().t_ws().then_preposition();

        let expr = SequenceExpr::aco("hope")
            .t_ws()
            .t_aco("your")
            .t_ws()
            .then_adjective()
            .then_optional(prep)
            .t_ws()
            .then(loc);

        Self { expr }
    }
}

impl ExprLinter for HopeYoure {
    type Unit = Chunk;

    fn expr(&self) -> &dyn crate::expr::Expr {
        &self.expr
    }

    fn match_to_lint(&self, toks: &[Token], src: &[char]) -> Option<Lint> {
        let your_tok = toks.get(2)?;
        let span = your_tok.span;
        let original = span.get_content(src);

        Some(Lint {
            span,
            lint_kind: LintKind::WordChoice,
            suggestions: vec![Suggestion::replace_with_match_case(
                "you're".chars().collect(),
                original,
            )],
            message: "Prefer `you're`—the contraction of “you are”—when expressing a hope about someone’s condition."
                .into(),
            priority: 31,
        })
    }

    fn description(&self) -> &str {
        "Detects the misuse of possessive **your** after “hope” and an adjective \
         (e.g., “I hope your well”) and advises using **you’re** to supply the \
         missing verb “are.”"
    }
}

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

    #[test]
    fn corrects_excited_here() {
        assert_suggestion_result(
            "I hope your excited here.",
            HopeYoure::default(),
            "I hope you're excited here.",
        );
    }

    #[test]
    fn corrects_safe_there() {
        assert_suggestion_result(
            "I hope your safe there.",
            HopeYoure::default(),
            "I hope you're safe there.",
        );
    }

    #[test]
    fn corrects_safe_over_there() {
        assert_suggestion_result(
            "I hope your safe over there.",
            HopeYoure::default(),
            "I hope you're safe over there.",
        );
    }

    #[test]
    fn corrects_fine_here() {
        assert_suggestion_result(
            "I hope your fine here.",
            HopeYoure::default(),
            "I hope you're fine here.",
        );
    }

    #[test]
    fn corrects_happy_there() {
        assert_suggestion_result(
            "I hope your happy there.",
            HopeYoure::default(),
            "I hope you're happy there.",
        );
    }

    #[test]
    fn corrects_healthy_out_here() {
        assert_suggestion_result(
            "I hope your healthy out here.",
            HopeYoure::default(),
            "I hope you're healthy out here.",
        );
    }

    #[test]
    fn corrects_strong_there() {
        assert_suggestion_result(
            "We hope your strong there.",
            HopeYoure::default(),
            "We hope you're strong there.",
        );
    }

    #[test]
    fn corrects_sorry_here() {
        assert_suggestion_result(
            "Hope your sorry here.",
            HopeYoure::default(),
            "Hope you're sorry here.",
        );
    }

    #[test]
    fn no_lint_with_contraction() {
        assert_lint_count("I hope you're excited here.", HopeYoure::default(), 0);
    }

    #[test]
    fn no_lint_without_adjective() {
        assert_lint_count("I hope your trip went well.", HopeYoure::default(), 0);
    }

    #[test]
    fn no_lint_with_following_clause() {
        assert_lint_count(
            "I hope your friends are well there.",
            HopeYoure::default(),
            0,
        );
    }

    #[test]
    fn no_lint_when_possessive_context() {
        assert_lint_count(
            "I hope your advice on punctuation is helpful.",
            HopeYoure::default(),
            0,
        );
    }
}