X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=clippy_lints%2Fsrc%2Fprecedence.rs;h=9cf00c953b95f16afd34ec6e047f944d534c840e;hb=9f6b5de7deaf4dc9e7917370ad09ab85dc23997c;hp=27e67bbe718cac08d4603ee6b8be5c3e28ddee13;hpb=dd06c06183e634b000198958c4ba9dc6d1f0616d;p=rust.git diff --git a/clippy_lints/src/precedence.rs b/clippy_lints/src/precedence.rs index 27e67bbe718..9cf00c953b9 100644 --- a/clippy_lints/src/precedence.rs +++ b/clippy_lints/src/precedence.rs @@ -1,9 +1,28 @@ -use crate::utils::{snippet_with_applicability, span_lint_and_sugg}; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::source::snippet_with_applicability; +use if_chain::if_chain; +use rustc_ast::ast::{BinOpKind, Expr, ExprKind, LitKind, UnOp}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; -use syntax::ast::*; + +const ALLOWED_ODD_FUNCTIONS: [&str; 14] = [ + "asin", + "asinh", + "atan", + "atanh", + "cbrt", + "fract", + "round", + "signum", + "sin", + "sinh", + "tan", + "tanh", + "to_degrees", + "to_radians", +]; declare_clippy_lint! { /// **What it does:** Checks for operations where precedence may be unclear @@ -85,29 +104,36 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { } } - if let ExprKind::Unary(UnOp::Neg, ref rhs) = expr.kind { - if let ExprKind::MethodCall(_, ref args) = rhs.kind { - if let Some(slf) = args.first() { - if let ExprKind::Lit(ref lit) = slf.kind { - match lit.kind { - LitKind::Int(..) | LitKind::Float(..) => { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - PRECEDENCE, - expr.span, - "unary minus has lower precedence than method call", - "consider adding parentheses to clarify your intent", - format!( - "-({})", - snippet_with_applicability(cx, rhs.span, "..", &mut applicability) - ), - applicability, - ); - }, - _ => (), - } - } + if let ExprKind::Unary(UnOp::Neg, operand) = &expr.kind { + let mut arg = operand; + + let mut all_odd = true; + while let ExprKind::MethodCall(path_segment, args, _) = &arg.kind { + let path_segment_str = path_segment.ident.name.as_str(); + all_odd &= ALLOWED_ODD_FUNCTIONS + .iter() + .any(|odd_function| **odd_function == *path_segment_str); + arg = args.first().expect("A method always has a receiver."); + } + + if_chain! { + if !all_odd; + if let ExprKind::Lit(lit) = &arg.kind; + if let LitKind::Int(..) | LitKind::Float(..) = &lit.kind; + then { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + PRECEDENCE, + expr.span, + "unary minus has lower precedence than method call", + "consider adding parentheses to clarify your intent", + format!( + "-({})", + snippet_with_applicability(cx, operand.span, "..", &mut applicability) + ), + applicability, + ); } } } @@ -123,18 +149,12 @@ fn is_arith_expr(expr: &Expr) -> bool { #[must_use] fn is_bit_op(op: BinOpKind) -> bool { - use syntax::ast::BinOpKind::*; - match op { - BitXor | BitAnd | BitOr | Shl | Shr => true, - _ => false, - } + use rustc_ast::ast::BinOpKind::{BitAnd, BitOr, BitXor, Shl, Shr}; + matches!(op, BitXor | BitAnd | BitOr | Shl | Shr) } #[must_use] fn is_arith_op(op: BinOpKind) -> bool { - use syntax::ast::BinOpKind::*; - match op { - Add | Sub | Mul | Div | Rem => true, - _ => false, - } + use rustc_ast::ast::BinOpKind::{Add, Div, Mul, Rem, Sub}; + matches!(op, Add | Sub | Mul | Div | Rem) }