]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/repeat_once.rs
Better handle method/function calls
[rust.git] / clippy_lints / src / repeat_once.rs
index d34e744eb944cd0631f0bc00b6d55ffdc6b6585c..898c70ace66f35776c42c3b6a866022af81c7751 100644 (file)
@@ -1,5 +1,7 @@
-use crate::consts::{constant_context, Constant};
-use crate::utils::{in_macro, is_type_diagnostic_item, snippet, span_lint_and_sugg};
+use clippy_utils::consts::{constant_context, Constant};
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::source::snippet;
+use clippy_utils::ty::is_type_diagnostic_item;
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_span::sym;
 
 declare_clippy_lint! {
-    /// **What it does:** Checks for usage of `.repeat(1)` and suggest the following method for each types.
+    /// ### What it does
+    /// Checks for usage of `.repeat(1)` and suggest the following method for each types.
     /// - `.to_string()` for `str`
     /// - `.clone()` for `String`
     /// - `.to_vec()` for `slice`
     ///
-    /// **Why is this bad?** For example, `String.repeat(1)` is equivalent to `.clone()`. If cloning the string is the intention behind this, `clone()` should be used.
+    /// The lint will evaluate constant expressions and values as arguments of `.repeat(..)` and emit a message if
+    /// they are equivalent to `1`. (Related discussion in [rust-clippy#7306](https://github.com/rust-lang/rust-clippy/issues/7306))
     ///
-    /// **Known problems:** None.
-    ///
-    /// **Example:**
+    /// ### Why is this bad?
+    /// For example, `String.repeat(1)` is equivalent to `.clone()`. If cloning
+    /// the string is the intention behind this, `clone()` should be used.
     ///
+    /// ### Example
     /// ```rust
     /// fn main() {
     ///     let x = String::from("hello world").repeat(1);
@@ -30,6 +35,7 @@
     ///     let x = String::from("hello world").clone();
     /// }
     /// ```
+    #[clippy::version = "1.47.0"]
     pub REPEAT_ONCE,
     complexity,
     "using `.repeat(1)` instead of `String.clone()`, `str.to_string()` or `slice.to_vec()` "
 impl<'tcx> LateLintPass<'tcx> for RepeatOnce {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'tcx Expr<'_>) {
         if_chain! {
-            if let ExprKind::MethodCall(path, _, [receiver, count], _) = &expr.kind;
+            if let ExprKind::MethodCall(path, [receiver, count], _) = &expr.kind;
             if path.ident.name == sym!(repeat);
-            if let Some(Constant::Int(1)) = constant_context(cx, cx.typeck_results()).expr(&count);
-            if !in_macro(receiver.span);
+            if constant_context(cx, cx.typeck_results()).expr(count) == Some(Constant::Int(1));
+            if !receiver.span.from_expansion();
             then {
-                let ty = cx.typeck_results().expr_ty(&receiver).peel_refs();
+                let ty = cx.typeck_results().expr_ty(receiver).peel_refs();
                 if ty.is_str() {
                     span_lint_and_sugg(
                         cx,
@@ -66,7 +72,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'tcx Expr<'_>) {
                         format!("{}.to_vec()", snippet(cx, receiver.span, r#""...""#)),
                         Applicability::MachineApplicable,
                     );
-                } else if is_type_diagnostic_item(cx, ty, sym::string_type) {
+                } else if is_type_diagnostic_item(cx, ty, sym::String) {
                     span_lint_and_sugg(
                         cx,
                         REPEAT_ONCE,