Move RepeatOnce
into Methods
lint pass
This commit is contained in:
parent
fd5376194a
commit
06d752e28d
7 changed files with 92 additions and 94 deletions
|
@ -197,6 +197,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec)
|
||||||
|
///
|
||||||
|
/// ### 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);
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// Use instead:
|
||||||
|
/// ```rust
|
||||||
|
/// fn main() {
|
||||||
|
/// 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()` "
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Methods {
|
pub struct Methods {
|
||||||
avoid_breaking_exported_api: bool,
|
avoid_breaking_exported_api: bool,
|
||||||
msrv: Option<RustcVersion>,
|
msrv: Option<RustcVersion>,
|
||||||
|
@ -2875,6 +2908,7 @@ impl_lint_pass!(Methods => [
|
||||||
NONSENSICAL_OPEN_OPTIONS,
|
NONSENSICAL_OPEN_OPTIONS,
|
||||||
PATH_BUF_PUSH_OVERWRITE,
|
PATH_BUF_PUSH_OVERWRITE,
|
||||||
RANGE_ZIP_WITH_LEN,
|
RANGE_ZIP_WITH_LEN,
|
||||||
|
REPEAT_ONCE,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/// Extracts a method call name, args, and `Span` of the method name.
|
/// Extracts a method call name, args, and `Span` of the method name.
|
||||||
|
@ -3263,6 +3297,9 @@ impl Methods {
|
||||||
("push", [arg]) => {
|
("push", [arg]) => {
|
||||||
path_buf_push_overwrite::check(cx, expr, arg);
|
path_buf_push_overwrite::check(cx, expr, arg);
|
||||||
},
|
},
|
||||||
|
("repeat", [arg]) => {
|
||||||
|
repeat_once::check(cx, expr, recv, arg);
|
||||||
|
},
|
||||||
("splitn" | "rsplitn", [count_arg, pat_arg]) => {
|
("splitn" | "rsplitn", [count_arg, pat_arg]) => {
|
||||||
if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
|
if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
|
||||||
suspicious_splitn::check(cx, name, expr, recv, count);
|
suspicious_splitn::check(cx, name, expr, recv, count);
|
||||||
|
|
52
clippy_lints/src/methods/repeat_once.rs
Normal file
52
clippy_lints/src/methods/repeat_once.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
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 rustc_errors::Applicability;
|
||||||
|
use rustc_hir::Expr;
|
||||||
|
use rustc_lint::LateContext;
|
||||||
|
use rustc_span::sym;
|
||||||
|
|
||||||
|
use super::REPEAT_ONCE;
|
||||||
|
|
||||||
|
pub(super) fn check<'tcx>(
|
||||||
|
cx: &LateContext<'tcx>,
|
||||||
|
expr: &'tcx Expr<'_>,
|
||||||
|
recv: &'tcx Expr<'_>,
|
||||||
|
repeat_arg: &'tcx Expr<'_>,
|
||||||
|
) {
|
||||||
|
if constant_context(cx, cx.typeck_results()).expr(repeat_arg) == Some(Constant::Int(1)) {
|
||||||
|
let ty = cx.typeck_results().expr_ty(recv).peel_refs();
|
||||||
|
if ty.is_str() {
|
||||||
|
span_lint_and_sugg(
|
||||||
|
cx,
|
||||||
|
REPEAT_ONCE,
|
||||||
|
expr.span,
|
||||||
|
"calling `repeat(1)` on str",
|
||||||
|
"consider using `.to_string()` instead",
|
||||||
|
format!("{}.to_string()", snippet(cx, recv.span, r#""...""#)),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
} else if ty.builtin_index().is_some() {
|
||||||
|
span_lint_and_sugg(
|
||||||
|
cx,
|
||||||
|
REPEAT_ONCE,
|
||||||
|
expr.span,
|
||||||
|
"calling `repeat(1)` on slice",
|
||||||
|
"consider using `.to_vec()` instead",
|
||||||
|
format!("{}.to_vec()", snippet(cx, recv.span, r#""...""#)),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
} else if is_type_diagnostic_item(cx, ty, sym::String) {
|
||||||
|
span_lint_and_sugg(
|
||||||
|
cx,
|
||||||
|
REPEAT_ONCE,
|
||||||
|
expr.span,
|
||||||
|
"calling `repeat(1)` on a string literal",
|
||||||
|
"consider using `.clone()` instead",
|
||||||
|
format!("{}.clone()", snippet(cx, recv.span, r#""...""#)),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,89 +0,0 @@
|
||||||
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_lint::{LateContext, LateLintPass};
|
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
|
||||||
use rustc_span::sym;
|
|
||||||
|
|
||||||
declare_clippy_lint! {
|
|
||||||
/// ### 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`
|
|
||||||
///
|
|
||||||
/// 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))
|
|
||||||
///
|
|
||||||
/// ### 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);
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
/// Use instead:
|
|
||||||
/// ```rust
|
|
||||||
/// fn main() {
|
|
||||||
/// 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()` "
|
|
||||||
}
|
|
||||||
|
|
||||||
declare_lint_pass!(RepeatOnce => [REPEAT_ONCE]);
|
|
||||||
|
|
||||||
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 path.ident.name == sym!(repeat);
|
|
||||||
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();
|
|
||||||
if ty.is_str() {
|
|
||||||
span_lint_and_sugg(
|
|
||||||
cx,
|
|
||||||
REPEAT_ONCE,
|
|
||||||
expr.span,
|
|
||||||
"calling `repeat(1)` on str",
|
|
||||||
"consider using `.to_string()` instead",
|
|
||||||
format!("{}.to_string()", snippet(cx, receiver.span, r#""...""#)),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
} else if ty.builtin_index().is_some() {
|
|
||||||
span_lint_and_sugg(
|
|
||||||
cx,
|
|
||||||
REPEAT_ONCE,
|
|
||||||
expr.span,
|
|
||||||
"calling `repeat(1)` on slice",
|
|
||||||
"consider using `.to_vec()` instead",
|
|
||||||
format!("{}.to_vec()", snippet(cx, receiver.span, r#""...""#)),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
} else if is_type_diagnostic_item(cx, ty, sym::String) {
|
|
||||||
span_lint_and_sugg(
|
|
||||||
cx,
|
|
||||||
REPEAT_ONCE,
|
|
||||||
expr.span,
|
|
||||||
"calling `repeat(1)` on a string literal",
|
|
||||||
"consider using `.clone()` instead",
|
|
||||||
format!("{}.clone()", snippet(cx, receiver.span, r#""...""#)),
|
|
||||||
Applicability::MachineApplicable,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue