Skip to content

Commit 1169066

Browse files
Araam Borhanianunknown
authored andcommitted
Adding lint for too many lines.
1 parent 5176a5c commit 1169066

21 files changed

+228
-13
lines changed

clippy_lints/src/assign_ops.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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/eq_op.rs

Lines changed: 1 addition & 1 deletion
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/functions.rs

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
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;
@@ -31,6 +31,22 @@ 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+
/// ```
44+
declare_clippy_lint! {
45+
pub TOO_MANY_LINES,
46+
pedantic,
47+
"functions with too many lines"
48+
}
49+
3450
/// **What it does:** Checks for public functions that dereferences raw pointer
3551
/// arguments but are not marked unsafe.
3652
///
@@ -62,17 +78,21 @@ declare_clippy_lint! {
6278
#[derive(Copy, Clone)]
6379
pub struct Functions {
6480
threshold: u64,
81+
max_lines: u64
6582
}
6683

6784
impl Functions {
68-
pub fn new(threshold: u64) -> Self {
69-
Self { threshold }
85+
pub fn new(threshold: u64, max_lines: u64) -> Self {
86+
Self {
87+
threshold,
88+
max_lines
89+
}
7090
}
7191
}
7292

7393
impl LintPass for Functions {
7494
fn get_lints(&self) -> LintArray {
75-
lint_array!(TOO_MANY_ARGUMENTS, NOT_UNSAFE_PTR_ARG_DEREF)
95+
lint_array!(TOO_MANY_ARGUMENTS, TOO_MANY_LINES, NOT_UNSAFE_PTR_ARG_DEREF)
7696
}
7797

7898
fn name(&self) -> &'static str {
@@ -123,6 +143,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
123143
}
124144

125145
self.check_raw_ptr(cx, unsafety, decl, body, nodeid);
146+
self.check_line_number(cx, span);
126147
}
127148

128149
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem) {
@@ -153,6 +174,54 @@ impl<'a, 'tcx> Functions {
153174
}
154175
}
155176

177+
fn check_line_number(self, cx: &LateContext, span: Span) {
178+
let code_snippet = snippet(cx, span, "..");
179+
let mut line_count = 0;
180+
let mut in_comment = false;
181+
for mut line in code_snippet.lines() {
182+
if in_comment {
183+
let end_comment_loc = match line.find("*/") {
184+
Some(i) => i,
185+
None => continue
186+
};
187+
in_comment = false;
188+
line = &line[end_comment_loc..];
189+
}
190+
line = line.trim_left();
191+
if line.is_empty() || line.starts_with("//") { continue; }
192+
if line.contains("/*") {
193+
let mut count_line: bool = !line.starts_with("/*");
194+
let close_counts = line.match_indices("*/").count();
195+
let open_counts = line.match_indices("/*").count();
196+
197+
if close_counts > 1 || open_counts > 1 {
198+
line_count += 1;
199+
} else if close_counts == 1 {
200+
match line.find("*/") {
201+
Some(i) => {
202+
line = line[i..].trim_left();
203+
if !line.is_empty() && !line.starts_with("//") {
204+
count_line = true;
205+
}
206+
},
207+
None => continue
208+
}
209+
} else {
210+
in_comment = true;
211+
}
212+
if count_line { line_count += 1; }
213+
} else {
214+
// No multipart comment, no single comment, non-empty string.
215+
line_count += 1;
216+
}
217+
}
218+
219+
if line_count > self.max_lines {
220+
span_lint(cx, TOO_MANY_LINES, span,
221+
"This function has a large number of lines.")
222+
}
223+
}
224+
156225
fn check_raw_ptr(
157226
self,
158227
cx: &LateContext<'a, 'tcx>,

clippy_lints/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ pub fn read_conf(reg: &rustc_plugin::Registry<'_>) -> Conf {
290290
}
291291
}
292292

293+
#[allow(clippy::too_many_lines)]
293294
#[rustfmt::skip]
294295
pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
295296
let mut store = reg.sess.lint_store.borrow_mut();
@@ -427,7 +428,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
427428
reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(
428429
conf.blacklisted_names.iter().cloned().collect()
429430
));
430-
reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold));
431+
reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold, conf.too_many_lines_threshold));
431432
reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.iter().cloned().collect()));
432433
reg.register_late_lint_pass(box neg_multiply::NegMultiply);
433434
reg.register_early_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval);
@@ -527,6 +528,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
527528
enum_glob_use::ENUM_GLOB_USE,
528529
enum_variants::MODULE_NAME_REPETITIONS,
529530
enum_variants::PUB_ENUM_VARIANT_NAMES,
531+
functions::TOO_MANY_LINES,
530532
if_not_else::IF_NOT_ELSE,
531533
infinite_iter::MAYBE_INFINITE_ITER,
532534
items_after_statements::ITEMS_AFTER_STATEMENTS,

clippy_lints/src/loops.rs

Lines changed: 2 additions & 0 deletions
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) {
@@ -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,

clippy_lints/src/methods/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
10051005
}
10061006

10071007
/// Checks for the `OR_FUN_CALL` lint.
1008+
#[allow(clippy::too_many_lines)]
10081009
fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) {
10091010
/// Check for `unwrap_or(T::new())` or `unwrap_or(T::default())`.
10101011
fn check_unwrap_or_default(
@@ -1151,6 +1152,7 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa
11511152
}
11521153

11531154
/// Checks for the `EXPECT_FUN_CALL` lint.
1155+
#[allow(clippy::too_many_lines)]
11541156
fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) {
11551157
// Strip `&`, `as_ref()` and `as_str()` off `arg` until we're left with either a `String` or
11561158
// `&str`

clippy_lints/src/needless_pass_by_value.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ macro_rules! need {
7373
}
7474

7575
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
76+
#[allow(clippy::too_many_lines)]
7677
fn check_fn(
7778
&mut self,
7879
cx: &LateContext<'a, 'tcx>,

clippy_lints/src/non_expressive_names.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> {
158158
);
159159
}
160160
}
161+
#[allow(clippy::too_many_lines)]
161162
fn check_name(&mut self, span: Span, name: Name) {
162163
let interned_name = name.as_str();
163164
if interned_name.chars().any(char::is_uppercase) {

clippy_lints/src/ptr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass {
151151
}
152152
}
153153

154+
#[allow(clippy::too_many_lines)]
154155
fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option<BodyId>) {
155156
let fn_def_id = cx.tcx.hir().local_def_id(fn_id);
156157
let sig = cx.tcx.fn_sig(fn_def_id);

0 commit comments

Comments
 (0)