forge_lint/sol/high/
incorrect_shift.rs

1use super::IncorrectShift;
2use crate::{
3    declare_forge_lint,
4    linter::{EarlyLintPass, LintContext},
5    sol::{Severity, SolLint},
6};
7use solar_ast::{BinOp, BinOpKind, Expr, ExprKind};
8
9declare_forge_lint!(
10    INCORRECT_SHIFT,
11    Severity::High,
12    "incorrect-shift",
13    "the order of args in a shift operation is incorrect"
14);
15
16impl<'ast> EarlyLintPass<'ast> for IncorrectShift {
17    fn check_expr(&mut self, ctx: &LintContext<'_>, expr: &'ast Expr<'ast>) {
18        if let ExprKind::Binary(
19            left_expr,
20            BinOp { kind: BinOpKind::Shl | BinOpKind::Shr, .. },
21            right_expr,
22        ) = &expr.kind
23        {
24            if contains_incorrect_shift(left_expr, right_expr) {
25                ctx.emit(&INCORRECT_SHIFT, expr.span);
26            }
27        }
28    }
29}
30
31// TODO: come up with a better heuristic. Treat initial impl as a PoC.
32// Checks if the left operand is a literal and the right operand is not, indicating a potential
33// reversed shift operation.
34fn contains_incorrect_shift<'ast>(
35    left_expr: &'ast Expr<'ast>,
36    right_expr: &'ast Expr<'ast>,
37) -> bool {
38    let is_left_literal = matches!(left_expr.kind, ExprKind::Lit(..));
39    let is_right_not_literal = !matches!(right_expr.kind, ExprKind::Lit(..));
40
41    is_left_literal && is_right_not_literal
42}