use crate::linting::expr_linter::Chunk;
use crate::{
Token,
expr::{Expr, SequenceExpr},
linting::{ExprLinter, Lint, LintKind, Suggestion},
};
pub struct FriendOfMe {
expr: SequenceExpr,
}
impl Default for FriendOfMe {
fn default() -> Self {
Self {
expr: SequenceExpr::word_set(&["friend", "friends", "enemy", "enemies"])
.then_whitespace()
.t_aco("of")
.t_ws()
.then_object_pronoun(),
}
}
}
impl ExprLinter for FriendOfMe {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
&self.expr
}
fn match_to_lint(&self, toks: &[Token], src: &[char]) -> Option<Lint> {
let obj_pron_tok = toks.last()?;
let obj_pron_str = obj_pron_tok.get_str(src);
let poss_pron_str = match obj_pron_str.as_str() {
"me" => "mine",
"you" => "yours",
"him" => "his",
"her" => return None,
"it" => return None,
"us" => "ours",
"them" => "theirs",
_ => return None,
};
Some(Lint {
span: obj_pron_tok.span,
lint_kind: LintKind::Grammar,
suggestions: vec![Suggestion::replace_with_match_case_str(
poss_pron_str,
obj_pron_tok.get_ch(src),
)],
message: format!("Use `{poss_pron_str}` instead of `{obj_pron_str}`."),
priority: 31,
})
}
fn description(&self) -> &'static str {
"Corrects wrong pronoun usage in constructions like `a friend of me`."
}
}
#[cfg(test)]
mod tests {
use super::FriendOfMe;
use crate::linting::tests::assert_suggestion_result;
#[test]
fn corrects_friend_of_me() {
assert_suggestion_result(
"Last year a friend of me died unexpectedly (not a close friend).",
FriendOfMe::default(),
"Last year a friend of mine died unexpectedly (not a close friend).",
);
}
#[test]
fn corrects_friend_of_you() {
assert_suggestion_result(
"imagine a friend of you wants to disturb your call, and send you a session-terminate with a wrong SID",
FriendOfMe::default(),
"imagine a friend of yours wants to disturb your call, and send you a session-terminate with a wrong SID",
);
}
#[test]
fn corrects_friend_of_us() {
assert_suggestion_result(
"You have denounced a friend of us! You have denounced an enemy of us.",
FriendOfMe::default(),
"You have denounced a friend of ours! You have denounced an enemy of ours.",
);
}
#[test]
fn corrects_friends_of_them() {
assert_suggestion_result(
"guest has friend and they see which friends of them are comming",
FriendOfMe::default(),
"guest has friend and they see which friends of theirs are comming",
);
}
#[test]
fn corrects_friend_of_him() {
assert_suggestion_result(
"Ah, got it, i thought you may was a friend of him",
FriendOfMe::default(),
"Ah, got it, i thought you may was a friend of his",
);
}
#[test]
fn corrects_friends_of_me() {
assert_suggestion_result(
"guest has friend and they see which friends of me are comming",
FriendOfMe::default(),
"guest has friend and they see which friends of mine are comming",
);
}
#[test]
fn corrects_friends_of_us() {
assert_suggestion_result(
"This project was created for friends of us.",
FriendOfMe::default(),
"This project was created for friends of ours.",
);
}
}