use crate::expr::Expr;
use crate::expr::SequenceExpr;
use crate::{Token, TokenStringExt};
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, Lint, LintKind, Suggestion};
pub struct LetUsRedundancy {
expr: Box<dyn Expr>,
}
impl Default for LetUsRedundancy {
fn default() -> Self {
let pattern = SequenceExpr::aco("let's").then_whitespace().then_pronoun();
Self {
expr: Box::new(pattern),
}
}
}
impl ExprLinter for LetUsRedundancy {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}
fn match_to_lint(&self, matched_tokens: &[Token], source: &[char]) -> Option<Lint> {
let template = matched_tokens.span()?.get_content(source);
let pronoun = matched_tokens.last()?.get_str(source);
Some(Lint {
span: matched_tokens.span()?,
lint_kind: LintKind::Repetition,
suggestions: vec![
Suggestion::replace_with_match_case(
format!("lets {pronoun}").chars().collect(),
template,
),
Suggestion::replace_with_match_case(
"let's".to_string().chars().collect(),
template,
),
],
message: "`let's` stands for `let us`, so including another pronoun is redundant."
.to_owned(),
priority: 31,
})
}
fn description(&self) -> &'static str {
"Many are not aware that the contraction `let's` is short for `let us`. As a result, many will incorrectly use it before a pronoun, such as in the phrase `let's us do`."
}
}