use crate::expr::{AnchorStart, Expr, SequenceExpr};
use crate::{Token, TokenKind};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct HavePronoun {
expr: SequenceExpr,
}
impl Default for HavePronoun {
fn default() -> Self {
let expr = SequenceExpr::with(AnchorStart)
.t_aco("has")
.t_ws()
.then_kind_either(
TokenKind::is_first_person_singular_pronoun,
TokenKind::is_plural_pronoun,
);
Self { expr }
}
}
impl ExprLinter for HavePronoun {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
&self.expr
}
fn match_to_lint(&self, toks: &[Token], src: &[char]) -> Option<Lint> {
let has_tok = toks.iter().find(|t| t.kind.is_word())?;
let span = has_tok.span;
let original = span.get_content(src);
Some(Lint {
span,
lint_kind: LintKind::Agreement,
suggestions: vec![Suggestion::replace_with_match_case(
"have".chars().collect(),
original,
)],
message: "Use `have` with first-person singular or plural pronouns.".to_owned(),
priority: 31,
})
}
fn description(&self) -> &'static str {
"Flags questions that begin with `has` followed by a pronoun that requires `have`, \
such as `Has we …` or `Has I …`, and suggests the correct auxiliary."
}
}
#[cfg(test)]
mod tests {
use super::HavePronoun;
use crate::linting::tests::{assert_lint_count, assert_suggestion_result};
#[test]
fn corrects_has_we() {
assert_suggestion_result(
"Has we finished the report?",
HavePronoun::default(),
"Have we finished the report?",
);
}
#[test]
fn corrects_has_you() {
assert_suggestion_result(
"Has you misunderstood?",
HavePronoun::default(),
"Have you misunderstood?",
);
}
#[test]
fn corrects_has_i() {
assert_suggestion_result(
"Has I misunderstood?",
HavePronoun::default(),
"Have I misunderstood?",
);
}
#[test]
fn corrects_has_they() {
assert_suggestion_result(
"Has they arrived yet?",
HavePronoun::default(),
"Have they arrived yet?",
);
}
#[test]
fn allows_has_he() {
assert_lint_count("Has he arrived yet?", HavePronoun::default(), 0);
}
#[test]
fn ignores_non_initial_usage() {
assert_lint_count(
"The system has we confused for a moment.",
HavePronoun::default(),
0,
);
}
}