Skip to content

Commit 4b736ff

Browse files
committed
Merge branch 'master' into issue3721
2 parents 60f723f + 3bda548 commit 4b736ff

Some content is hidden

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

48 files changed

+554
-124
lines changed

.travis.yml

+19-14
Original file line numberDiff line numberDiff line change
@@ -39,40 +39,45 @@ install:
3939
matrix:
4040
fast_finish: true
4141
include:
42+
# Builds that are executed for every PR
4243
- os: osx # run base tests on both platforms
4344
env: BASE_TESTS=true
4445
- os: linux
4546
env: BASE_TESTS=true
4647
- os: windows
4748
env: CARGO_INCREMENTAL=0 BASE_TESTS=true
49+
50+
# Builds that are only executed when a PR is r+ed or a try build is started
51+
# We don't want to run these always because they go towards
52+
# the build limit within the Travis rust-lang account.
4853
- env: INTEGRATION=rust-lang/cargo
49-
if: repo =~ /^rust-lang\/rust-clippy$/
54+
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
5055
- env: INTEGRATION=rust-random/rand
51-
if: repo =~ /^rust-lang\/rust-clippy$/
56+
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
5257
- env: INTEGRATION=rust-lang-nursery/stdsimd
53-
if: repo =~ /^rust-lang\/rust-clippy$/
58+
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
5459
- env: INTEGRATION=rust-lang/rustfmt
55-
if: repo =~ /^rust-lang\/rust-clippy$/
60+
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
5661
- env: INTEGRATION=rust-lang-nursery/futures-rs
57-
if: repo =~ /^rust-lang\/rust-clippy$/
62+
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
5863
- env: INTEGRATION=rust-lang-nursery/failure
59-
if: repo =~ /^rust-lang\/rust-clippy$/
64+
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
6065
- env: INTEGRATION=rust-lang-nursery/log
61-
if: repo =~ /^rust-lang\/rust-clippy$/
66+
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
6267
- env: INTEGRATION=rust-lang-nursery/chalk
63-
if: repo =~ /^rust-lang\/rust-clippy$/
68+
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
6469
- env: INTEGRATION=rust-lang/rls
65-
if: repo =~ /^rust-lang\/rust-clippy$/
70+
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
6671
- env: INTEGRATION=chronotope/chrono
67-
if: repo =~ /^rust-lang\/rust-clippy$/
72+
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
6873
- env: INTEGRATION=serde-rs/serde
69-
if: repo =~ /^rust-lang\/rust-clippy$/
74+
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
7075
- env: INTEGRATION=Geal/nom
71-
if: repo =~ /^rust-lang\/rust-clippy$/
76+
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
7277
- env: INTEGRATION=hyperium/hyper
73-
if: repo =~ /^rust-lang\/rust-clippy$/
78+
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
7479
- env: INTEGRATION=bluss/rust-itertools
75-
if: repo =~ /^rust-lang\/rust-clippy$/
80+
if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try)
7681
allow_failures:
7782
- os: windows
7883
env: CARGO_INCREMENTAL=0 BASE_TESTS=true

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,7 @@ All notable changes to this project will be documented in this file.
982982
[`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment
983983
[`temporary_cstring_as_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_cstring_as_ptr
984984
[`too_many_arguments`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_arguments
985+
[`too_many_lines`]: https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines
985986
[`toplevel_ref_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#toplevel_ref_arg
986987
[`transmute_bytes_to_str`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_bytes_to_str
987988
[`transmute_int_to_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_bool

clippy_lints/src/assign_ops.rs

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ impl LintPass for AssignOps {
6464
}
6565

6666
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps {
67+
#[allow(clippy::too_many_lines)]
6768
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
6869
match &expr.node {
6970
hir::ExprKind::AssignOp(op, lhs, rhs) => {

clippy_lints/src/bit_mask.rs

+1
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ fn check_compare(cx: &LateContext<'_, '_>, bit_op: &Expr, cmp_op: BinOpKind, cmp
177177
}
178178
}
179179

180+
#[allow(clippy::too_many_lines)]
180181
fn check_bit_mask(
181182
cx: &LateContext<'_, '_>,
182183
bit_op: BinOpKind,

clippy_lints/src/blacklisted_name.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ impl LintPass for BlackListedName {
4444

4545
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlackListedName {
4646
fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) {
47-
if let PatKind::Binding(_, _, ident, _) = pat.node {
47+
if let PatKind::Binding(.., ident, _) = pat.node {
4848
if self.blacklist.contains(&ident.name.to_string()) {
4949
span_lint(
5050
cx,

clippy_lints/src/copies.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ fn bindings<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, pat: &Pat) -> FxHashMap<LocalI
286286
bindings_impl(cx, pat, map);
287287
}
288288
},
289-
PatKind::Binding(_, _, ident, ref as_pat) => {
289+
PatKind::Binding(.., ident, ref as_pat) => {
290290
if let Entry::Vacant(v) = map.entry(ident.as_str()) {
291291
v.insert(cx.tables.pat_ty(pat));
292292
}

clippy_lints/src/eq_op.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ impl LintPass for EqOp {
5959
}
6060

6161
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EqOp {
62-
#[allow(clippy::similar_names)]
62+
#[allow(clippy::similar_names, clippy::too_many_lines)]
6363
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) {
6464
if let ExprKind::Binary(op, ref left, ref right) = e.node {
6565
if in_macro(e.span) {

clippy_lints/src/eta_reduction.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ fn check_closure(cx: &LateContext<'_, '_>, expr: &Expr) {
8181
_ => (),
8282
}
8383
for (a1, a2) in iter_input_pats(decl, body).zip(args) {
84-
if let PatKind::Binding(_, _, ident, _) = a1.pat.node {
84+
if let PatKind::Binding(.., ident, _) = a1.pat.node {
8585
// XXXManishearth Should I be checking the binding mode here?
8686
if let ExprKind::Path(QPath::Resolved(None, ref p)) = a2.node {
8787
if p.segments.len() != 1 {

clippy_lints/src/functions.rs

+97-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use crate::utils::{iter_input_pats, span_lint, type_is_unsafe_function};
1+
use crate::utils::{iter_input_pats, snippet, span_lint, type_is_unsafe_function};
22
use matches::matches;
33
use rustc::hir;
44
use rustc::hir::def::Def;
55
use rustc::hir::intravisit;
6-
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
6+
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
77
use rustc::ty;
88
use rustc::{declare_tool_lint, lint_array};
99
use rustc_data_structures::fx::FxHashSet;
@@ -31,6 +31,29 @@ declare_clippy_lint! {
3131
"functions with too many arguments"
3232
}
3333

34+
/// **What it does:** Checks for functions with a large amount of lines.
35+
///
36+
/// **Why is this bad?** Functions with a lot of lines are harder to understand
37+
/// due to having to look at a larger amount of code to understand what the
38+
/// function is doing. Consider splitting the body of the function into
39+
/// multiple functions.
40+
///
41+
/// **Known problems:** None.
42+
///
43+
/// **Example:**
44+
/// ``` rust
45+
/// fn im_too_long() {
46+
/// println!("");
47+
/// // ... 100 more LoC
48+
/// println!("");
49+
/// }
50+
/// ```
51+
declare_clippy_lint! {
52+
pub TOO_MANY_LINES,
53+
pedantic,
54+
"functions with too many lines"
55+
}
56+
3457
/// **What it does:** Checks for public functions that dereferences raw pointer
3558
/// arguments but are not marked unsafe.
3659
///
@@ -62,17 +85,18 @@ declare_clippy_lint! {
6285
#[derive(Copy, Clone)]
6386
pub struct Functions {
6487
threshold: u64,
88+
max_lines: u64,
6589
}
6690

6791
impl Functions {
68-
pub fn new(threshold: u64) -> Self {
69-
Self { threshold }
92+
pub fn new(threshold: u64, max_lines: u64) -> Self {
93+
Self { threshold, max_lines }
7094
}
7195
}
7296

7397
impl LintPass for Functions {
7498
fn get_lints(&self) -> LintArray {
75-
lint_array!(TOO_MANY_ARGUMENTS, NOT_UNSAFE_PTR_ARG_DEREF)
99+
lint_array!(TOO_MANY_ARGUMENTS, TOO_MANY_LINES, NOT_UNSAFE_PTR_ARG_DEREF)
76100
}
77101

78102
fn name(&self) -> &'static str {
@@ -123,6 +147,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
123147
}
124148

125149
self.check_raw_ptr(cx, unsafety, decl, body, nodeid);
150+
self.check_line_number(cx, span);
126151
}
127152

128153
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem) {
@@ -153,6 +178,72 @@ impl<'a, 'tcx> Functions {
153178
}
154179
}
155180

181+
fn check_line_number(self, cx: &LateContext<'_, '_>, span: Span) {
182+
if in_external_macro(cx.sess(), span) {
183+
return;
184+
}
185+
186+
let code_snippet = snippet(cx, span, "..");
187+
let mut line_count: u64 = 0;
188+
let mut in_comment = false;
189+
let mut code_in_line;
190+
191+
// Skip the surrounding function decl.
192+
let start_brace_idx = match code_snippet.find('{') {
193+
Some(i) => i + 1,
194+
None => 0,
195+
};
196+
let end_brace_idx = match code_snippet.find('}') {
197+
Some(i) => i,
198+
None => code_snippet.len(),
199+
};
200+
let function_lines = code_snippet[start_brace_idx..end_brace_idx].lines();
201+
202+
for mut line in function_lines {
203+
code_in_line = false;
204+
loop {
205+
line = line.trim_start();
206+
if line.is_empty() {
207+
break;
208+
}
209+
if in_comment {
210+
match line.find("*/") {
211+
Some(i) => {
212+
line = &line[i + 2..];
213+
in_comment = false;
214+
continue;
215+
},
216+
None => break,
217+
}
218+
} else {
219+
let multi_idx = match line.find("/*") {
220+
Some(i) => i,
221+
None => line.len(),
222+
};
223+
let single_idx = match line.find("//") {
224+
Some(i) => i,
225+
None => line.len(),
226+
};
227+
code_in_line |= multi_idx > 0 && single_idx > 0;
228+
// Implies multi_idx is below line.len()
229+
if multi_idx < single_idx {
230+
line = &line[multi_idx + 2..];
231+
in_comment = true;
232+
continue;
233+
}
234+
break;
235+
}
236+
}
237+
if code_in_line {
238+
line_count += 1;
239+
}
240+
}
241+
242+
if line_count > self.max_lines {
243+
span_lint(cx, TOO_MANY_LINES, span, "This function has a large number of lines.")
244+
}
245+
}
246+
156247
fn check_raw_ptr(
157248
self,
158249
cx: &LateContext<'a, 'tcx>,
@@ -183,7 +274,7 @@ impl<'a, 'tcx> Functions {
183274
}
184275

185276
fn raw_ptr_arg(arg: &hir::Arg, ty: &hir::Ty) -> Option<ast::NodeId> {
186-
if let (&hir::PatKind::Binding(_, id, _, _), &hir::TyKind::Ptr(_)) = (&arg.pat.node, &ty.node) {
277+
if let (&hir::PatKind::Binding(_, id, _, _, _), &hir::TyKind::Ptr(_)) = (&arg.pat.node, &ty.node) {
187278
Some(id)
188279
} else {
189280
None

clippy_lints/src/large_enum_variant.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant {
9494
|db| {
9595
if variant.fields.len() == 1 {
9696
let span = match def.variants[i].node.data {
97-
VariantData::Struct(ref fields, _) | VariantData::Tuple(ref fields, _) => {
97+
VariantData::Struct(ref fields, ..) | VariantData::Tuple(ref fields, ..) => {
9898
fields[0].ty.span
9999
},
100-
VariantData::Unit(_) => unreachable!(),
100+
VariantData::Unit(..) => unreachable!(),
101101
};
102102
if let Some(snip) = snippet_opt(cx, span) {
103103
db.span_suggestion(

clippy_lints/src/let_if_seq.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetIfSeq {
7373
if_chain! {
7474
if let Some(expr) = it.peek();
7575
if let hir::StmtKind::Local(ref local) = stmt.node;
76-
if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.node;
76+
if let hir::PatKind::Binding(mode, canonical_id, _, ident, None) = local.pat.node;
7777
if let hir::StmtKind::Expr(ref if_) = expr.node;
7878
if let hir::ExprKind::If(ref cond, ref then, ref else_) = if_.node;
7979
if !used_in_expr(cx, canonical_id, cond);

clippy_lints/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ pub fn read_conf(reg: &rustc_plugin::Registry<'_>) -> Conf {
292292
}
293293
}
294294

295+
#[allow(clippy::too_many_lines)]
295296
#[rustfmt::skip]
296297
pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
297298
let mut store = reg.sess.lint_store.borrow_mut();
@@ -429,7 +430,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
429430
reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(
430431
conf.blacklisted_names.iter().cloned().collect()
431432
));
432-
reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold));
433+
reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold, conf.too_many_lines_threshold));
433434
reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.iter().cloned().collect()));
434435
reg.register_late_lint_pass(box neg_multiply::NegMultiply);
435436
reg.register_early_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval);
@@ -530,6 +531,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
530531
enum_glob_use::ENUM_GLOB_USE,
531532
enum_variants::MODULE_NAME_REPETITIONS,
532533
enum_variants::PUB_ENUM_VARIANT_NAMES,
534+
functions::TOO_MANY_LINES,
533535
if_not_else::IF_NOT_ELSE,
534536
infinite_iter::MAYBE_INFINITE_ITER,
535537
items_after_statements::ITEMS_AFTER_STATEMENTS,

clippy_lints/src/loops.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ impl LintPass for Pass {
472472
}
473473

474474
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
475+
#[allow(clippy::too_many_lines)]
475476
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
476477
// we don't want to check expanded macros
477478
if in_macro(expr.span) {
@@ -968,7 +969,7 @@ fn detect_manual_memcpy<'a, 'tcx>(
968969
}) = higher::range(cx, arg)
969970
{
970971
// the var must be a single name
971-
if let PatKind::Binding(_, canonical_id, _, _) = pat.node {
972+
if let PatKind::Binding(_, canonical_id, _, _, _) = pat.node {
972973
let print_sum = |arg1: &Offset, arg2: &Offset| -> String {
973974
match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) {
974975
("0", _, "0", _) => "".into(),
@@ -1066,6 +1067,7 @@ fn detect_manual_memcpy<'a, 'tcx>(
10661067

10671068
/// Check for looping over a range and then indexing a sequence with it.
10681069
/// The iteratee must be a range literal.
1070+
#[allow(clippy::too_many_lines)]
10691071
fn check_for_loop_range<'a, 'tcx>(
10701072
cx: &LateContext<'a, 'tcx>,
10711073
pat: &'tcx Pat,
@@ -1084,7 +1086,7 @@ fn check_for_loop_range<'a, 'tcx>(
10841086
}) = higher::range(cx, arg)
10851087
{
10861088
// the var must be a single name
1087-
if let PatKind::Binding(_, canonical_id, ident, _) = pat.node {
1089+
if let PatKind::Binding(_, canonical_id, _, ident, _) = pat.node {
10881090
let mut visitor = VarVisitor {
10891091
cx,
10901092
var: canonical_id,
@@ -1635,7 +1637,7 @@ fn check_for_mutability(cx: &LateContext<'_, '_>, bound: &Expr) -> Option<NodeId
16351637
let node_str = cx.tcx.hir().get(node_id);
16361638
if_chain! {
16371639
if let Node::Binding(pat) = node_str;
1638-
if let PatKind::Binding(bind_ann, _, _, _) = pat.node;
1640+
if let PatKind::Binding(bind_ann, ..) = pat.node;
16391641
if let BindingAnnotation::Mutable = bind_ann;
16401642
then {
16411643
return Some(node_id);
@@ -1668,7 +1670,7 @@ fn check_for_mutation(
16681670
fn pat_is_wild<'tcx>(pat: &'tcx PatKind, body: &'tcx Expr) -> bool {
16691671
match *pat {
16701672
PatKind::Wild => true,
1671-
PatKind::Binding(_, _, ident, None) if ident.as_str().starts_with('_') => {
1673+
PatKind::Binding(.., ident, None) if ident.as_str().starts_with('_') => {
16721674
let mut visitor = UsedVisitor {
16731675
var: ident.name,
16741676
used: false,
@@ -2093,7 +2095,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InitializeVisitor<'a, 'tcx> {
20932095
// Look for declarations of the variable
20942096
if let StmtKind::Local(ref local) = stmt.node {
20952097
if local.pat.id == self.var_id {
2096-
if let PatKind::Binding(_, _, ident, _) = local.pat.node {
2098+
if let PatKind::Binding(.., ident, _) = local.pat.node {
20972099
self.name = Some(ident.name);
20982100

20992101
self.state = if let Some(ref init) = local.init {
@@ -2284,7 +2286,7 @@ impl<'tcx> Visitor<'tcx> for LoopNestVisitor {
22842286
if self.nesting != Unknown {
22852287
return;
22862288
}
2287-
if let PatKind::Binding(_, _, span_name, _) = pat.node {
2289+
if let PatKind::Binding(.., span_name, _) = pat.node {
22882290
if self.iterator == span_name.name {
22892291
self.nesting = RuledOut;
22902292
return;

0 commit comments

Comments
 (0)