Skip to content

Commit a8d80d5

Browse files
committed
Move GetFirst into Methods lint pass
1 parent e3b7797 commit a8d80d5

File tree

7 files changed

+76
-75
lines changed

7 files changed

+76
-75
lines changed

clippy_lints/src/get_first.rs

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

clippy_lints/src/lib.register_all.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
8181
LintId::of(functions::NOT_UNSAFE_PTR_ARG_DEREF),
8282
LintId::of(functions::RESULT_UNIT_ERR),
8383
LintId::of(functions::TOO_MANY_ARGUMENTS),
84-
LintId::of(get_first::GET_FIRST),
8584
LintId::of(if_let_mutex::IF_LET_MUTEX),
8685
LintId::of(indexing_slicing::OUT_OF_BOUNDS_INDEXING),
8786
LintId::of(infinite_iter::INFINITE_ITER),
@@ -162,6 +161,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
162161
LintId::of(methods::FILTER_MAP_IDENTITY),
163162
LintId::of(methods::FILTER_NEXT),
164163
LintId::of(methods::FLAT_MAP_IDENTITY),
164+
LintId::of(methods::GET_FIRST),
165165
LintId::of(methods::GET_LAST_WITH_LEN),
166166
LintId::of(methods::INSPECT_FOR_EACH),
167167
LintId::of(methods::INTO_ITER_ON_REF),

clippy_lints/src/lib.register_lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ store.register_lints(&[
174174
functions::TOO_MANY_ARGUMENTS,
175175
functions::TOO_MANY_LINES,
176176
future_not_send::FUTURE_NOT_SEND,
177-
get_first::GET_FIRST,
178177
if_let_mutex::IF_LET_MUTEX,
179178
if_not_else::IF_NOT_ELSE,
180179
if_then_some_else_none::IF_THEN_SOME_ELSE_NONE,
@@ -302,6 +301,7 @@ store.register_lints(&[
302301
methods::FLAT_MAP_IDENTITY,
303302
methods::FLAT_MAP_OPTION,
304303
methods::FROM_ITER_INSTEAD_OF_COLLECT,
304+
methods::GET_FIRST,
305305
methods::GET_LAST_WITH_LEN,
306306
methods::GET_UNWRAP,
307307
methods::IMPLICIT_CLONE,

clippy_lints/src/lib.register_style.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
2929
LintId::of(functions::DOUBLE_MUST_USE),
3030
LintId::of(functions::MUST_USE_UNIT),
3131
LintId::of(functions::RESULT_UNIT_ERR),
32-
LintId::of(get_first::GET_FIRST),
3332
LintId::of(inherent_to_string::INHERENT_TO_STRING),
3433
LintId::of(init_numbered_fields::INIT_NUMBERED_FIELDS),
3534
LintId::of(len_zero::COMPARISON_TO_EMPTY),
@@ -62,6 +61,7 @@ store.register_group(true, "clippy::style", Some("clippy_style"), vec![
6261
LintId::of(methods::CHARS_LAST_CMP),
6362
LintId::of(methods::CHARS_NEXT_CMP),
6463
LintId::of(methods::ERR_EXPECT),
64+
LintId::of(methods::GET_FIRST),
6565
LintId::of(methods::INTO_ITER_ON_REF),
6666
LintId::of(methods::IS_DIGIT_ASCII_RADIX),
6767
LintId::of(methods::ITER_CLONED_COLLECT),

clippy_lints/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,6 @@ mod from_over_into;
233233
mod from_str_radix_10;
234234
mod functions;
235235
mod future_not_send;
236-
mod get_first;
237236
mod if_let_mutex;
238237
mod if_not_else;
239238
mod if_then_some_else_none;
@@ -907,7 +906,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
907906
store.register_late_pass(|| Box::new(strings::TrimSplitWhitespace));
908907
store.register_late_pass(|| Box::new(rc_clone_in_vec_init::RcCloneInVecInit));
909908
store.register_early_pass(|| Box::new(duplicate_mod::DuplicateMod::default()));
910-
store.register_late_pass(|| Box::new(get_first::GetFirst));
911909
store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding));
912910
store.register_early_pass(move || Box::new(almost_complete_letter_range::AlmostCompleteLetterRange::new(msrv)));
913911
store.register_late_pass(|| Box::new(swap_ptr_to_ref::SwapPtrToRef));

clippy_lints/src/methods/get_first.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use clippy_utils::is_slice_of_primitives;
3+
use clippy_utils::source::snippet_with_applicability;
4+
use if_chain::if_chain;
5+
use rustc_ast::LitKind;
6+
use rustc_errors::Applicability;
7+
use rustc_hir as hir;
8+
use rustc_lint::LateContext;
9+
use rustc_span::source_map::Spanned;
10+
11+
use super::GET_FIRST;
12+
13+
pub(super) fn check<'tcx>(
14+
cx: &LateContext<'tcx>,
15+
expr: &'tcx hir::Expr<'_>,
16+
recv: &'tcx hir::Expr<'_>,
17+
arg: &'tcx hir::Expr<'_>,
18+
) {
19+
if_chain! {
20+
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
21+
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
22+
if cx.tcx.type_of(impl_id).is_slice();
23+
if let Some(_) = is_slice_of_primitives(cx, recv);
24+
if let hir::ExprKind::Lit(Spanned { node: LitKind::Int(0, _), .. }) = arg.kind;
25+
then {
26+
let mut app = Applicability::MachineApplicable;
27+
let slice_name = snippet_with_applicability(cx, recv.span, "..", &mut app);
28+
span_lint_and_sugg(
29+
cx,
30+
GET_FIRST,
31+
expr.span,
32+
&format!("accessing first element with `{0}.get(0)`", slice_name),
33+
"try",
34+
format!("{}.first()", slice_name),
35+
app,
36+
);
37+
}
38+
}
39+
}

clippy_lints/src/methods/mod.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ mod filter_next;
2424
mod flat_map_identity;
2525
mod flat_map_option;
2626
mod from_iter_instead_of_collect;
27+
mod get_first;
2728
mod get_last_with_len;
2829
mod get_unwrap;
2930
mod implicit_clone;
@@ -2457,6 +2458,32 @@ declare_clippy_lint! {
24572458
"Checks for calls to ends_with with case-sensitive file extensions"
24582459
}
24592460

2461+
declare_clippy_lint! {
2462+
/// ### What it does
2463+
/// Checks for using `x.get(0)` instead of
2464+
/// `x.first()`.
2465+
///
2466+
/// ### Why is this bad?
2467+
/// Using `x.first()` is easier to read and has the same
2468+
/// result.
2469+
///
2470+
/// ### Example
2471+
/// ```rust
2472+
/// let x = vec![2, 3, 5];
2473+
/// let first_element = x.get(0);
2474+
/// ```
2475+
///
2476+
/// Use instead:
2477+
/// ```rust
2478+
/// let x = vec![2, 3, 5];
2479+
/// let first_element = x.first();
2480+
/// ```
2481+
#[clippy::version = "1.63.0"]
2482+
pub GET_FIRST,
2483+
style,
2484+
"Using `x.get(0)` when `x.first()` is simpler"
2485+
}
2486+
24602487
pub struct Methods {
24612488
avoid_breaking_exported_api: bool,
24622489
msrv: Option<RustcVersion>,
@@ -2564,6 +2591,7 @@ impl_lint_pass!(Methods => [
25642591
NAIVE_BYTECOUNT,
25652592
BYTES_COUNT_TO_LEN,
25662593
CASE_SENSITIVE_FILE_EXTENSION_COMPARISONS,
2594+
GET_FIRST,
25672595
]);
25682596

25692597
/// Extracts a method call name, args, and `Span` of the method name.
@@ -2833,7 +2861,8 @@ impl Methods {
28332861
},
28342862
("ends_with", [arg]) => {
28352863
if let ExprKind::MethodCall(_, _, span) = expr.kind {
2836-
case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg);
2864+
case_sensitive_file_extension_comparisons::check(cx, expr, span, recv, arg);
2865+
}
28372866
},
28382867
("expect", [_]) => match method_call(recv) {
28392868
Some(("ok", [recv], _)) => ok_expect::check(cx, expr, recv),
@@ -2867,7 +2896,10 @@ impl Methods {
28672896
inspect_for_each::check(cx, expr, span2);
28682897
}
28692898
},
2870-
("get", [arg]) => get_last_with_len::check(cx, expr, recv, arg),
2899+
("get", [arg]) => {
2900+
get_first::check(cx, expr, recv, arg);
2901+
get_last_with_len::check(cx, expr, recv, arg);
2902+
},
28712903
("get_or_insert_with", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "get_or_insert"),
28722904
("is_file", []) => filetype_is_file::check(cx, expr, recv),
28732905
("is_digit", [radix]) => is_digit_ascii_radix::check(cx, expr, recv, radix, self.msrv),

0 commit comments

Comments
 (0)