use crate::expr::{Expr, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, Lint, LintKind, Suggestion};
use crate::token::Token;
use crate::token_string_ext::TokenStringExt;
pub struct MoreBetter {
expr: SequenceExpr,
}
impl Default for MoreBetter {
fn default() -> Self {
Self {
expr: SequenceExpr::any_of(vec![
Box::new(
SequenceExpr::default()
.t_aco("more")
.t_ws()
.then_comparative_adjective(),
),
Box::new(
SequenceExpr::default()
.t_aco("most")
.t_ws()
.then_superlative_adjective(),
),
]),
}
}
}
impl ExprLinter for MoreBetter {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
&self.expr
}
fn match_to_lint(&self, toks: &[Token], src: &[char]) -> Option<Lint> {
let phrase_span = toks.span()?;
let degree_str = toks.first()?.get_str(src);
let adj_span = toks.last()?.span;
let suggestion = Suggestion::replace_with_match_case(
adj_span.get_content(src).to_vec(),
phrase_span.get_content(src),
);
let message = format!(
"{} is already in the {} form, the {} is redundant",
adj_span.get_content_string(src),
if degree_str.eq_ignore_ascii_case("more") {
"comparative"
} else {
"superlative"
},
degree_str,
);
Some(Lint {
span: phrase_span,
lint_kind: LintKind::Redundancy,
suggestions: vec![suggestion],
message,
..Default::default()
})
}
fn description(&self) -> &'static str {
"Finds redundant paring of `more` or `most` with adjectives already in the comparative or superlative form."
}
}
#[cfg(test)]
mod tests {
use super::MoreBetter;
use crate::linting::tests::assert_suggestion_result;
#[test]
fn flag_most_biggest() {
assert_suggestion_result("Most biggest", MoreBetter::default(), "Biggest");
}
#[test]
fn flag_more_better_and_more_better() {
assert_suggestion_result(
"More bigger is more better",
MoreBetter::default(),
"Bigger is better",
);
}
}