Skip to main content

wowlab_tidy/languages/rust/rules/style/
yoda_conditions.rs

1use ra_ap_syntax::ast::{self, BinaryOp, CmpOp};
2
3use crate::{AstCtx, Example, Violation};
4
5#[rustfmt::skip]
6const EXAMPLES: &[Example] = &[
7    Example {
8        label: "literal on left eq",
9        code: "fn f(x: i32) { if 0 == x {} }",
10        pass: false,
11    },
12    Example {
13        label: "literal on right",
14        code: "fn f(x: i32) { if x == 0 {} }",
15        pass: true,
16    },
17    Example {
18        label: "literal on left ne",
19        code: "fn f(y: i32) { if 1 != y {} }",
20        pass: false,
21    },
22    Example {
23        label: "both literals",
24        code: r#"fn f() { if "a" == "b" {} }"#,
25        pass: true,
26    },
27    Example {
28        label: "non-comparison",
29        code: "fn f(x: i32) { let _ = 1 + x; }",
30        pass: true,
31    },
32    Example {
33        label: "yoda in test module",
34        code: "#[cfg(test)]\nmod tests {\n  fn t(x: i32) { if 0 == x {} }\n}",
35        pass: true,
36    },
37];
38
39crate::ast_rule!(
40    yoda_conditions,
41    "Flag reversed comparisons like `0 == x` — prefer `x == 0`.",
42    "In Rust there is no accidental assignment in conditions, so the C-style 0 == x guard is unnecessary and harder to read.",
43);
44
45fn check_yoda_conditions(ctx: &AstCtx<'_>) -> Vec<Violation> {
46    ctx.nodes::<ast::BinExpr>()
47        .filter(|expr| {
48            !ctx.is_in_test(expr)
49                && matches!(expr.op_kind(), Some(BinaryOp::CmpOp(CmpOp::Eq { .. })))
50        })
51        .filter_map(|expr| {
52            let (left, right) = expr.sub_exprs();
53            let (left, right) = (left?, right?);
54
55            (matches!(left, ast::Expr::Literal(_)) && !matches!(right, ast::Expr::Literal(_)))
56                .then(|| ctx.violation(&left, "Yoda condition — put the literal on the right side"))
57        })
58        .collect()
59}
60
61crate::tidy_ast_test!(check_yoda_conditions, {
62    crate::example_tests!(EXAMPLES, check_yoda_conditions);
63});