Skip to content

Commit 2730f94

Browse files
committed
Move methods lint declarations into sub-modules
1 parent 9a1d1b6 commit 2730f94

File tree

146 files changed

+4906
-5225
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

146 files changed

+4906
-5225
lines changed

clippy_lints_methods/src/bind_instead_of_map.rs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{BIND_INSTEAD_OF_MAP, contains_return};
1+
use super::contains_return;
22
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
33
use clippy_utils::peel_blocks;
44
use clippy_utils::source::{snippet, snippet_with_context};
@@ -10,6 +10,38 @@ use rustc_hir::{LangItem, QPath};
1010
use rustc_lint::LateContext;
1111
use rustc_span::Span;
1212

13+
declare_clippy_lint! {
14+
/// ### What it does
15+
/// Checks for usage of `_.and_then(|x| Some(y))`, `_.and_then(|x| Ok(y))`
16+
/// or `_.or_else(|x| Err(y))`.
17+
///
18+
/// ### Why is this bad?
19+
/// This can be written more concisely as `_.map(|x| y)` or `_.map_err(|x| y)`.
20+
///
21+
/// ### Example
22+
/// ```no_run
23+
/// # fn opt() -> Option<&'static str> { Some("42") }
24+
/// # fn res() -> Result<&'static str, &'static str> { Ok("42") }
25+
/// let _ = opt().and_then(|s| Some(s.len()));
26+
/// let _ = res().and_then(|s| if s.len() == 42 { Ok(10) } else { Ok(20) });
27+
/// let _ = res().or_else(|s| if s.len() == 42 { Err(10) } else { Err(20) });
28+
/// ```
29+
///
30+
/// The correct use would be:
31+
///
32+
/// ```no_run
33+
/// # fn opt() -> Option<&'static str> { Some("42") }
34+
/// # fn res() -> Result<&'static str, &'static str> { Ok("42") }
35+
/// let _ = opt().map(|s| s.len());
36+
/// let _ = res().map(|s| if s.len() == 42 { 10 } else { 20 });
37+
/// let _ = res().map_err(|s| if s.len() == 42 { 10 } else { 20 });
38+
/// ```
39+
#[clippy::version = "1.45.0"]
40+
pub BIND_INSTEAD_OF_MAP,
41+
complexity,
42+
"using `Option.and_then(|x| Some(y))`, which is more succinctly expressed as `map(|x| y)`"
43+
}
44+
1345
pub(super) fn check_and_then_some(
1446
cx: &LateContext<'_>,
1547
expr: &hir::Expr<'_>,

clippy_lints_methods/src/bytecount.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,36 @@ use rustc_lint::LateContext;
99
use rustc_middle::ty::{self, UintTy};
1010
use rustc_span::sym;
1111

12-
use super::NAIVE_BYTECOUNT;
12+
declare_clippy_lint! {
13+
/// ### What it does
14+
/// Checks for naive byte counts
15+
///
16+
/// ### Why is this bad?
17+
/// The [`bytecount`](https://crates.io/crates/bytecount)
18+
/// crate has methods to count your bytes faster, especially for large slices.
19+
///
20+
/// ### Known problems
21+
/// If you have predominantly small slices, the
22+
/// `bytecount::count(..)` method may actually be slower. However, if you can
23+
/// ensure that less than 2³²-1 matches arise, the `naive_count_32(..)` can be
24+
/// faster in those cases.
25+
///
26+
/// ### Example
27+
/// ```no_run
28+
/// # let vec = vec![1_u8];
29+
/// let count = vec.iter().filter(|x| **x == 0u8).count();
30+
/// ```
31+
///
32+
/// Use instead:
33+
/// ```rust,ignore
34+
/// # let vec = vec![1_u8];
35+
/// let count = bytecount::count(&vec, 0u8);
36+
/// ```
37+
#[clippy::version = "pre 1.29.0"]
38+
pub NAIVE_BYTECOUNT,
39+
pedantic,
40+
"use of naive `<slice>.filter(|&x| x == y).count()` to count byte values"
41+
}
1342

1443
pub(super) fn check<'tcx>(
1544
cx: &LateContext<'tcx>,

clippy_lints_methods/src/bytes_count_to_len.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,30 @@ use rustc_errors::Applicability;
55
use rustc_hir as hir;
66
use rustc_lint::LateContext;
77

8-
use super::BYTES_COUNT_TO_LEN;
8+
declare_clippy_lint! {
9+
/// ### What it does
10+
/// It checks for `str::bytes().count()` and suggests replacing it with
11+
/// `str::len()`.
12+
///
13+
/// ### Why is this bad?
14+
/// `str::bytes().count()` is longer and may not be as performant as using
15+
/// `str::len()`.
16+
///
17+
/// ### Example
18+
/// ```no_run
19+
/// "hello".bytes().count();
20+
/// String::from("hello").bytes().count();
21+
/// ```
22+
/// Use instead:
23+
/// ```no_run
24+
/// "hello".len();
25+
/// String::from("hello").len();
26+
/// ```
27+
#[clippy::version = "1.62.0"]
28+
pub BYTES_COUNT_TO_LEN,
29+
complexity,
30+
"Using `bytes().count()` when `len()` performs the same functionality"
31+
}
932

1033
pub(super) fn check<'tcx>(
1134
cx: &LateContext<'tcx>,

clippy_lints_methods/src/bytes_nth.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,28 @@ use rustc_lint::LateContext;
88

99
use crate::method_call;
1010

11-
use super::BYTES_NTH;
11+
declare_clippy_lint! {
12+
/// ### What it does
13+
/// Checks for the use of `.bytes().nth()`.
14+
///
15+
/// ### Why is this bad?
16+
/// `.as_bytes().get()` is more efficient and more
17+
/// readable.
18+
///
19+
/// ### Example
20+
/// ```no_run
21+
/// "Hello".bytes().nth(3);
22+
/// ```
23+
///
24+
/// Use instead:
25+
/// ```no_run
26+
/// "Hello".as_bytes().get(3);
27+
/// ```
28+
#[clippy::version = "1.52.0"]
29+
pub BYTES_NTH,
30+
style,
31+
"replace `.bytes().nth()` with `.as_bytes().get()`"
32+
}
1233

1334
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, recv: &'tcx Expr<'tcx>, n_arg: &'tcx Expr<'tcx>) {
1435
let ty = cx.typeck_results().expr_ty(recv).peel_refs();

clippy_lints_methods/src/case_sensitive_file_extension_comparisons.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,33 @@ use rustc_lint::LateContext;
1010
use rustc_span::Span;
1111
use rustc_span::source_map::Spanned;
1212

13-
use super::CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS;
13+
declare_clippy_lint! {
14+
/// ### What it does
15+
/// Checks for calls to `ends_with` with possible file extensions
16+
/// and suggests to use a case-insensitive approach instead.
17+
///
18+
/// ### Why is this bad?
19+
/// `ends_with` is case-sensitive and may not detect files with a valid extension.
20+
///
21+
/// ### Example
22+
/// ```no_run
23+
/// fn is_rust_file(filename: &str) -> bool {
24+
/// filename.ends_with(".rs")
25+
/// }
26+
/// ```
27+
/// Use instead:
28+
/// ```no_run
29+
/// fn is_rust_file(filename: &str) -> bool {
30+
/// let filename = std::path::Path::new(filename);
31+
/// filename.extension()
32+
/// .map_or(false, |ext| ext.eq_ignore_ascii_case("rs"))
33+
/// }
34+
/// ```
35+
#[clippy::version = "1.51.0"]
36+
pub CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS,
37+
pedantic,
38+
"Checks for calls to ends_with with case-sensitive file extensions"
39+
}
1440

1541
pub(super) fn check<'tcx>(
1642
cx: &LateContext<'tcx>,

clippy_lints_methods/src/chars_cmp.rs

Lines changed: 135 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,112 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::source::snippet_with_applicability;
3-
use clippy_utils::{method_chain_args, path_def_id};
3+
use clippy_utils::{method_chain_args, path_def_id, sym};
44
use rustc_errors::Applicability;
5-
use rustc_hir as hir;
65
use rustc_lint::{LateContext, Lint};
76
use rustc_middle::ty;
87
use rustc_span::Symbol;
8+
use {rustc_ast as ast, rustc_hir as hir};
9+
10+
declare_clippy_lint! {
11+
/// ### What it does
12+
/// Checks for usage of `.chars().next()` on a `str` to check
13+
/// if it starts with a given char.
14+
///
15+
/// ### Why is this bad?
16+
/// Readability, this can be written more concisely as
17+
/// `_.starts_with(_)`.
18+
///
19+
/// ### Example
20+
/// ```no_run
21+
/// let name = "foo";
22+
/// if name.chars().next() == Some('_') {};
23+
/// ```
24+
///
25+
/// Use instead:
26+
/// ```no_run
27+
/// let name = "foo";
28+
/// if name.starts_with('_') {};
29+
/// ```
30+
#[clippy::version = "pre 1.29.0"]
31+
pub CHARS_NEXT_CMP,
32+
style,
33+
"using `.chars().next()` to check if a string starts with a char"
34+
}
35+
36+
declare_clippy_lint! {
37+
/// ### What it does
38+
/// Checks for usage of `_.chars().last()` or
39+
/// `_.chars().next_back()` on a `str` to check if it ends with a given char.
40+
///
41+
/// ### Why is this bad?
42+
/// Readability, this can be written more concisely as
43+
/// `_.ends_with(_)`.
44+
///
45+
/// ### Example
46+
/// ```no_run
47+
/// # let name = "_";
48+
/// name.chars().last() == Some('_') || name.chars().next_back() == Some('-');
49+
/// ```
50+
///
51+
/// Use instead:
52+
/// ```no_run
53+
/// # let name = "_";
54+
/// name.ends_with('_') || name.ends_with('-');
55+
/// ```
56+
#[clippy::version = "pre 1.29.0"]
57+
pub CHARS_LAST_CMP,
58+
style,
59+
"using `.chars().last()` or `.chars().next_back()` to check if a string ends with a char"
60+
}
61+
62+
/// Checks for the `CHARS_NEXT_CMP` lint.
63+
pub(super) fn check_next(cx: &LateContext<'_>, info: &crate::BinaryExprInfo<'_>) -> bool {
64+
check(cx, info, &[sym::chars, sym::next], CHARS_NEXT_CMP, "starts_with")
65+
}
66+
67+
/// Checks for the `CHARS_NEXT_CMP` lint with `unwrap()`.
68+
pub(super) fn check_next_unwrap(cx: &LateContext<'_>, info: &crate::BinaryExprInfo<'_>) -> bool {
69+
check_unwrap(
70+
cx,
71+
info,
72+
&[sym::chars, sym::next, sym::unwrap],
73+
CHARS_NEXT_CMP,
74+
"starts_with",
75+
)
76+
}
77+
78+
/// Checks for the `CHARS_LAST_CMP` lint.
79+
pub(super) fn check_last(cx: &LateContext<'_>, info: &crate::BinaryExprInfo<'_>) -> bool {
80+
if check(cx, info, &[sym::chars, sym::last], CHARS_LAST_CMP, "ends_with") {
81+
true
82+
} else {
83+
check(cx, info, &[sym::chars, sym::next_back], CHARS_LAST_CMP, "ends_with")
84+
}
85+
}
86+
87+
/// Checks for the `CHARS_LAST_CMP` lint with `unwrap()`.
88+
pub(super) fn check_last_unwrap(cx: &LateContext<'_>, info: &crate::BinaryExprInfo<'_>) -> bool {
89+
if check_unwrap(
90+
cx,
91+
info,
92+
&[sym::chars, sym::last, sym::unwrap],
93+
CHARS_LAST_CMP,
94+
"ends_with",
95+
) {
96+
true
97+
} else {
98+
check_unwrap(
99+
cx,
100+
info,
101+
&[sym::chars, sym::next_back, sym::unwrap],
102+
CHARS_LAST_CMP,
103+
"ends_with",
104+
)
105+
}
106+
}
9107

10108
/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints.
11-
pub(super) fn check(
109+
fn check(
12110
cx: &LateContext<'_>,
13111
info: &crate::BinaryExprInfo<'_>,
14112
chain_methods: &[Symbol],
@@ -47,3 +145,37 @@ pub(super) fn check(
47145

48146
false
49147
}
148+
149+
/// Wrapper fn for `CHARS_NEXT_CMP` and `CHARS_LAST_CMP` lints with `unwrap()`.
150+
fn check_unwrap(
151+
cx: &LateContext<'_>,
152+
info: &crate::BinaryExprInfo<'_>,
153+
chain_methods: &[Symbol],
154+
lint: &'static Lint,
155+
suggest: &str,
156+
) -> bool {
157+
if let Some(args) = method_chain_args(info.chain, chain_methods)
158+
&& let hir::ExprKind::Lit(lit) = info.other.kind
159+
&& let ast::LitKind::Char(c) = lit.node
160+
{
161+
let mut applicability = Applicability::MachineApplicable;
162+
span_lint_and_sugg(
163+
cx,
164+
lint,
165+
info.expr.span,
166+
format!("you should use the `{suggest}` method"),
167+
"like this",
168+
format!(
169+
"{}{}.{suggest}('{}')",
170+
if info.eq { "" } else { "!" },
171+
snippet_with_applicability(cx, args[0].0.span, "..", &mut applicability),
172+
c.escape_default()
173+
),
174+
applicability,
175+
);
176+
177+
true
178+
} else {
179+
false
180+
}
181+
}

clippy_lints_methods/src/chars_cmp_with_unwrap.rs

Lines changed: 0 additions & 42 deletions
This file was deleted.

clippy_lints_methods/src/chars_last_cmp.rs

Lines changed: 0 additions & 14 deletions
This file was deleted.

0 commit comments

Comments
 (0)