| use clippy_utils::diagnostics::span_lint_and_sugg; | |
| use clippy_utils::sugg::Sugg; | |
| use clippy_utils::{eq_expr_value, sym}; | |
| use rustc_errors::Applicability; | |
| use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment}; | |
| use rustc_lint::LateContext; | |
| use rustc_span::Spanned; | |
| use super::SUBOPTIMAL_FLOPS; | |
| fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool { | |
| if let ExprKind::MethodCall(PathSegment { ident: method_a, .. }, _, args_a, _) = expr_a.kind | |
| && let ExprKind::MethodCall(PathSegment { ident: method_b, .. }, _, args_b, _) = expr_b.kind | |
| { | |
| return method_a.name == method_b.name | |
| && args_a.len() == args_b.len() | |
| && (matches!(method_a.name, sym::ln | sym::log2 | sym::log10) | |
| || method_a.name == sym::log && args_a.len() == 1 && eq_expr_value(cx, &args_a[0], &args_b[0])); | |
| } | |
| false | |
| } | |
| pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { | |
| // check if expression of the form x.logN() / y.logN() | |
| if let ExprKind::Binary( | |
| Spanned { | |
| node: BinOpKind::Div, .. | |
| }, | |
| lhs, | |
| rhs, | |
| ) = expr.kind | |
| && are_same_base_logs(cx, lhs, rhs) | |
| && let ExprKind::MethodCall(_, largs_self, ..) = lhs.kind | |
| && let ExprKind::MethodCall(_, rargs_self, ..) = rhs.kind | |
| { | |
| let mut app = Applicability::MachineApplicable; | |
| span_lint_and_sugg( | |
| cx, | |
| SUBOPTIMAL_FLOPS, | |
| expr.span, | |
| "log base can be expressed more clearly", | |
| "consider using", | |
| format!( | |
| "{}.log({})", | |
| Sugg::hir_with_applicability(cx, largs_self, "_", &mut app).maybe_paren(), | |
| Sugg::hir_with_applicability(cx, rargs_self, "_", &mut app), | |
| ), | |
| app, | |
| ); | |
| } | |
| } |