harper-core 2.13.0

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

pub struct HighLowStandards {
    expr: SequenceExpr,
}

impl Default for HighLowStandards {
    fn default() -> Self {
        Self {
            expr: SequenceExpr::word_set(["got", "had", "has", "have", "having"])
                .then_optional(SequenceExpr::whitespace().then_degree_adverb())
                .t_ws()
                .t_set(["high", "low"])
                .t_ws()
                .t_aco("standard")
                .then_any_of([
                    Box::new(AnchorEnd) as Box<dyn Expr>,
                    Box::new(SequenceExpr::whitespace().then(|t: &Token, s: &[char]| {
                        (t.kind.is_preposition() && !t.get_ch(s).eq_str("of"))
                            || t.get_ch(s)
                                .eq_any_ignore_ascii_case_str(&["and", "even", "when"])
                    })),
                ]),
        }
    }
}

impl ExprLinter for HighLowStandards {
    type Unit = Chunk;

    fn match_to_lint(&self, toks: &[Token], src: &[char]) -> Option<Lint> {
        let span =
            find_the_only_token_matching(toks, src, |t, _| t.get_ch(src).eq_str("standard"))?.span;

        Some(Lint {
            span,
            lint_kind: LintKind::Usage,
            suggestions: vec![Suggestion::replace_with_match_case_str(
                "standards",
                span.get_content(src),
            )],
            message: "This idiom uses plural `standards`.".to_owned(),
            ..Default::default()
        })
    }

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

    fn description(&self) -> &str {
        "Corrects `high/low standard` to `high/low standards` when `standard` is a noun."
    }
}

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

    use super::HighLowStandards;

    #[test]
    fn at_end() {
        assert_suggestion_result(
            "I have low standard",
            HighLowStandards::default(),
            "I have low standards",
        );
    }

    #[test]
    fn followed_by_for() {
        assert_suggestion_result(
            "I have high standard for men",
            HighLowStandards::default(),
            "I have high standards for men",
        );
    }

    #[test]
    fn dont_flag_standard_deviation() {
        assert_no_lints(
            "It's very difficult for any model to predict accurately when trained with data having such high standard deviation.",
            HighLowStandards::default(),
        );
    }

    #[test]
    fn dont_flag_followed_by_when() {
        assert_suggestion_result(
            "I tend to have high standard when answering questions.",
            HighLowStandards::default(),
            "I tend to have high standards when answering questions.",
        );
    }

    #[test]
    fn followed_by_comma() {
        assert_suggestion_result(
            "Most student would choose supervisor who doesn’t have high standard, but what i did is precisely the opposite.",
            HighLowStandards::default(),
            "Most student would choose supervisor who doesn’t have high standards, but what i did is precisely the opposite.",
        );
    }

    #[test]
    fn very_high() {
        assert_suggestion_result(
            "I picked a supervisor who has very high standard, strict, and very well detailed.",
            HighLowStandards::default(),
            "I picked a supervisor who has very high standards, strict, and very well detailed.",
        );
    }

    #[test]
    fn followed_by_and() {
        assert_suggestion_result(
            "Great way to tell you have low standard and can't detect latency.",
            HighLowStandards::default(),
            "Great way to tell you have low standards and can't detect latency.",
        );
    }

    #[test]
    fn dont_flag_standard_of_living() {
        assert_no_lints(
            "US has high standard of living, but it is not among the top 5 countreis with the highest minimum hourly-wage.",
            HighLowStandards::default(),
        );
    }

    #[test]
    fn followed_by_on() {
        assert_suggestion_result(
            "We should also recognize the fact that, Swedes have very high standard on their expectation of English fluency.",
            HighLowStandards::default(),
            "We should also recognize the fact that, Swedes have very high standards on their expectation of English fluency.",
        );
    }

    #[test]
    fn followed_by_in() {
        assert_suggestion_result(
            "We have high standard in product manufacturing and foreign trade",
            HighLowStandards::default(),
            "We have high standards in product manufacturing and foreign trade",
        );
    }
}