use crate::expr::Expr;
use crate::{Token, patterns::Word};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
type InitialismWord = Vec<char>;
type InitialismPhrase = Vec<InitialismWord>;
pub struct InitialismLinter {
expr: Word,
expansions_lower: Vec<InitialismPhrase>,
}
impl InitialismLinter {
pub fn new(initialism: &str, expansions: &[&str]) -> Self {
let expansions_lower = expansions
.iter()
.map(|expansion| {
expansion
.split(' ')
.map(|s| s.chars().map(|v| v.to_ascii_lowercase()).collect())
.collect()
})
.collect();
Self {
expr: Word::from_char_string(initialism.chars().collect()),
expansions_lower,
}
}
}
impl ExprLinter for InitialismLinter {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
&self.expr
}
fn match_to_lint(&self, matched_tokens: &[Token], source: &[char]) -> Option<Lint> {
let tok = matched_tokens.first()?;
let source = tok.get_ch(source);
let suggestions = self
.expansions_lower
.iter()
.map(|expansion_lower| {
let mut expansion = expansion_lower.clone();
let first_letter = &mut expansion[0][0];
*first_letter = if source[0].is_ascii_uppercase() {
first_letter.to_ascii_uppercase()
} else {
first_letter.to_ascii_lowercase()
};
Suggestion::ReplaceWith(
expansion
.iter()
.flat_map(|word| std::iter::once(' ').chain(word.iter().copied()))
.skip(1)
.collect::<Vec<_>>(),
)
})
.collect::<Vec<_>>();
Some(Lint {
span: tok.span,
lint_kind: LintKind::Miscellaneous,
suggestions,
message: "Try expanding this initialism.".to_owned(),
priority: 127,
})
}
fn description(&self) -> &'static str {
"Expands an initialism."
}
}
#[cfg(test)]
mod tests {}