Skip to content

Commit

Permalink
Add lint for iter.nth(0)
Browse files Browse the repository at this point in the history
- Encourage iter.next() rather than iter.nth(0),
  which is less readable
  • Loading branch information
bradsherman committed Dec 28, 2019
1 parent 578e712 commit 315667e
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1141,6 +1141,7 @@ Released 2018-09-13
[`iter_cloned_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_cloned_collect
[`iter_next_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_next_loop
[`iter_nth`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_nth
[`iter_nth_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_nth_zero
[`iter_skip_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_next
[`iterator_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iterator_step_by_zero
[`just_underscores_and_digits`]: https://rust-lang.github.io/rust-clippy/master/index.html#just_underscores_and_digits
Expand Down
57 changes: 57 additions & 0 deletions clippy_lints/src/iter_nth_zero.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
use crate::utils::span_lint_and_sugg;

use rustc::declare_lint_pass;
use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use rustc_errors::Applicability;
use rustc_session::declare_tool_lint;
use syntax::ast::{Expr, ExprKind, PathSegment};

declare_clippy_lint! {
/// **What it does:** Checks for the use of `iter.nth(0)`.
///
/// **Why is this bad?** `iter.nth(0)` is unnecessary, and `iter.next()`
/// is more readable.
///
/// **Known problems:** None.
///
/// **Example:**
///
/// ```rust,ignore
/// // Bad
/// let mut s = HashSet::new();
/// s.insert(1);
/// let x = s.iter().nth(0);
///
/// // Good
/// let mut s = HashSet::new();
/// s.insert(1);
/// let x = s.iter().next();
/// ```
pub ITER_NTH_ZERO,
style,
"replace `iter.nth(0)` with `iter.next()`"
}

declare_lint_pass!(IterNthZero => [ITER_NTH_ZERO]);

impl EarlyLintPass for IterNthZero {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
if let ExprKind::MethodCall(PathSegment { ident, .. }, args) = &expr.kind {
if ident.name.as_str() == "nth" {
if let ExprKind::Lit(literal) = &args[1].kind {
if literal.token.symbol.as_str() == "0" {
span_lint_and_sugg(
cx,
ITER_NTH_ZERO,
expr.span,
"calling `iter.nth(0)` is redundant",
"try",
"using `iter.next()` instead".to_string(),
Applicability::MachineApplicable,
);
}
}
}
}
}
}
5 changes: 5 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ pub mod inline_fn_without_body;
pub mod int_plus_one;
pub mod integer_division;
pub mod items_after_statements;
pub mod iter_nth_zero;
pub mod large_enum_variant;
pub mod large_stack_arrays;
pub mod len_zero;
Expand Down Expand Up @@ -554,6 +555,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
&int_plus_one::INT_PLUS_ONE,
&integer_division::INTEGER_DIVISION,
&items_after_statements::ITEMS_AFTER_STATEMENTS,
&iter_nth_zero::ITER_NTH_ZERO,
&large_enum_variant::LARGE_ENUM_VARIANT,
&large_stack_arrays::LARGE_STACK_ARRAYS,
&len_zero::LEN_WITHOUT_IS_EMPTY,
Expand Down Expand Up @@ -980,6 +982,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
store.register_early_pass(|| box as_conversions::AsConversions);
store.register_early_pass(|| box utils::internal_lints::ProduceIce);
store.register_late_pass(|| box let_underscore::LetUnderscore);
store.register_early_pass(|| box iter_nth_zero::IterNthZero);

store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
LintId::of(&arithmetic::FLOAT_ARITHMETIC),
Expand Down Expand Up @@ -1146,6 +1149,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
LintId::of(&inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY),
LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY),
LintId::of(&int_plus_one::INT_PLUS_ONE),
LintId::of(&iter_nth_zero::ITER_NTH_ZERO),
LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT),
LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
LintId::of(&len_zero::LEN_ZERO),
Expand Down Expand Up @@ -1352,6 +1356,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
LintId::of(&functions::MUST_USE_UNIT),
LintId::of(&infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH),
LintId::of(&inherent_to_string::INHERENT_TO_STRING),
LintId::of(&iter_nth_zero::ITER_NTH_ZERO),
LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
LintId::of(&len_zero::LEN_ZERO),
LintId::of(&let_if_seq::USELESS_LET_IF_SEQ),
Expand Down
7 changes: 7 additions & 0 deletions src/lintlist/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,13 @@ pub const ALL_LINTS: [Lint; 342] = [
deprecation: None,
module: "methods",
},
Lint {
name: "iter_nth_zero",
group: "style",
desc: "replace `iter.nth(0)` with `iter.next()`",
deprecation: None,
module: "iter_nth_zero",
},
Lint {
name: "iter_skip_next",
group: "style",
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/iter_nth_zero.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#![warn(clippy::iter_nth_zero)]
use std::collections::HashSet;

fn main() {
let mut s = HashSet::new();
s.insert(1);
let x = s.iter().nth(0);
}
10 changes: 10 additions & 0 deletions tests/ui/iter_nth_zero.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: calling `iter.nth(0)` is redundant
--> $DIR/iter_nth_zero.rs:7:13
|
LL | let x = s.iter().nth(0);
| ^^^^^^^^^^^^^^^ help: try: `using `iter.next()` instead`
|
= note: `-D clippy::iter-nth-zero` implied by `-D warnings`

error: aborting due to previous error

0 comments on commit 315667e

Please sign in to comment.