forge_lint/sol/med/
div_mul.rs
1use super::DivideBeforeMultiply;
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 DIVIDE_BEFORE_MULTIPLY,
11 Severity::Med,
12 "divide-before-multiply",
13 "multiplication should occur before division to avoid loss of precision"
14);
15
16impl<'ast> EarlyLintPass<'ast> for DivideBeforeMultiply {
17 fn check_expr(&mut self, ctx: &LintContext<'_>, expr: &'ast Expr<'ast>) {
18 if let ExprKind::Binary(left_expr, BinOp { kind: BinOpKind::Mul, .. }, _) = &expr.kind {
19 if contains_division(left_expr) {
20 ctx.emit(&DIVIDE_BEFORE_MULTIPLY, expr.span);
21 }
22 }
23 }
24}
25
26fn contains_division<'ast>(expr: &'ast Expr<'ast>) -> bool {
27 match &expr.kind {
28 ExprKind::Binary(_, BinOp { kind: BinOpKind::Div, .. }, _) => true,
29 ExprKind::Tuple(inner_exprs) => inner_exprs.iter().any(|opt_expr| {
30 if let Some(inner_expr) = opt_expr {
31 contains_division(inner_expr)
32 } else {
33 false
34 }
35 }),
36 _ => false,
37 }
38}