use crate::{
CharStringExt, Lint, Token,
expr::{Expr, SequenceExpr},
linting::{ExprLinter, LintKind, Suggestion, expr_linter::Chunk},
};
pub struct ImplementIn {
expr: SequenceExpr,
}
impl Default for ImplementIn {
fn default() -> Self {
Self {
expr: SequenceExpr::word_set(&[
"implement",
"implemented",
"implementing",
"implements",
])
.t_ws()
.then_any_of([
Box::new(SequenceExpr::aco("into")),
Box::new(SequenceExpr::any_word().t_ws().t_aco("into")),
]),
}
}
}
impl ExprLinter for ImplementIn {
type Unit = Chunk;
fn match_to_lint(&self, toks: &[Token], src: &[char]) -> Option<Lint> {
let (vtok, midtok, itok) = match toks.len() {
3 => (&toks[0], None, &toks[2]),
5 => (&toks[0], Some(&toks[2]), &toks[4]),
_ => return None,
};
if vtok.kind.is_noun() && midtok.is_some_and(|t| t.kind.is_verb() && !t.kind.is_noun()) {
return None;
}
if (midtok.is_none() || midtok.is_some_and(|t| t.get_ch(src).eq_ch(&['t', 'h', 'e'])))
&& itok.get_ch(src) == ['I', 'n', 't', 'o']
{
return None;
}
let span = toks.last()?.span;
Some(Lint {
span,
lint_kind: LintKind::Usage,
suggestions: vec![Suggestion::replace_with_match_case_str(
"in",
span.get_content(src),
)],
message: "Prefer `in` over `into` in this usage.".to_owned(),
..Default::default()
})
}
fn expr(&self) -> &dyn Expr {
&self.expr
}
fn description(&self) -> &str {
"Corrects nonstandard `implement into` to `implement in`."
}
}
#[cfg(test)]
mod tests {
use crate::linting::tests::{assert_no_lints, assert_suggestion_result};
use super::ImplementIn;
#[test]
fn fix_implement_something_lowercase() {
assert_suggestion_result(
"How to implement overlay into your code?",
ImplementIn::default(),
"How to implement overlay in your code?",
);
}
#[test]
fn fix_implement_something_titlecase() {
assert_suggestion_result(
"Implement Connectors into the Testbed",
ImplementIn::default(),
"Implement Connectors in the Testbed",
);
}
#[test]
fn fix_implement_something() {
assert_suggestion_result(
"So why not implement it into links or w3m?",
ImplementIn::default(),
"So why not implement it in links or w3m?",
);
}
#[test]
fn fix_implement_into() {
assert_suggestion_result(
"Use ngx-daterangepicker-material as Storybook Angular (Issue about Ranges Clicked and Dates Updated) when implement into other project",
ImplementIn::default(),
"Use ngx-daterangepicker-material as Storybook Angular (Issue about Ranges Clicked and Dates Updated) when implement in other project",
);
}
#[test]
fn fix_implemented_into() {
assert_suggestion_result(
"Demo of MCTS AI implemented into a platformer with a level editor.",
ImplementIn::default(),
"Demo of MCTS AI implemented in a platformer with a level editor.",
);
}
#[test]
fn fix_implemented_something() {
assert_suggestion_result(
"Trained and implemented autoencoder into a pipeline with Google Cloud transcription API",
ImplementIn::default(),
"Trained and implemented autoencoder in a pipeline with Google Cloud transcription API",
);
}
#[test]
fn fix_implementing_something() {
assert_suggestion_result(
"Problem with implementing library into the Vue.js webpack-based project",
ImplementIn::default(),
"Problem with implementing library in the Vue.js webpack-based project",
);
}
#[test]
fn fix_implementing_something_title_case() {
assert_suggestion_result(
"Implementing breadcrumbs into site with AngularJS v1.2.16.",
ImplementIn::default(),
"Implementing breadcrumbs in site with AngularJS v1.2.16.",
);
}
#[test]
fn fix_implements_something() {
assert_suggestion_result(
"A plugin that implements latex into discord.",
ImplementIn::default(),
"A plugin that implements latex in discord.",
);
}
#[test]
fn dont_flag_implements_into_trait() {
assert_no_lints(
"I suppose there is a concern that somebody may define a struct which implements Into",
ImplementIn::default(),
);
}
#[test]
fn dont_flag_implementing_into_trait() {
assert_no_lints(
"There might still be cases where one cannot implement From but implementing Into is possible.",
ImplementIn::default(),
);
}
#[test]
fn dont_flag_implementing_the_into_trait() {
assert_no_lints(
"I'm having trouble implementing the Into trait for a generic struct in Rust.",
ImplementIn::default(),
);
}
}