]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs
Rollup merge of #85802 - Thomasdezeeuw:ioslice-advance, r=m-ou-se
[rust.git] / src / tools / clippy / clippy_lints / src / functions / too_many_lines.rs
1 use rustc_hir as hir;
2 use rustc_lint::{LateContext, LintContext};
3 use rustc_middle::lint::in_external_macro;
4 use rustc_span::Span;
5
6 use clippy_utils::diagnostics::span_lint;
7 use clippy_utils::source::snippet_opt;
8
9 use super::TOO_MANY_LINES;
10
11 pub(super) fn check_fn(cx: &LateContext<'_>, span: Span, body: &'tcx hir::Body<'_>, too_many_lines_threshold: u64) {
12     if in_external_macro(cx.sess(), span) {
13         return;
14     }
15
16     let code_snippet = match snippet_opt(cx, body.value.span) {
17         Some(s) => s,
18         _ => return,
19     };
20     let mut line_count: u64 = 0;
21     let mut in_comment = false;
22     let mut code_in_line;
23
24     let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..))
25         && code_snippet.as_bytes().first().copied() == Some(b'{')
26         && code_snippet.as_bytes().last().copied() == Some(b'}')
27     {
28         // Removing the braces from the enclosing block
29         &code_snippet[1..code_snippet.len() - 1]
30     } else {
31         &code_snippet
32     }
33     .trim() // Remove leading and trailing blank lines
34     .lines();
35
36     for mut line in function_lines {
37         code_in_line = false;
38         loop {
39             line = line.trim_start();
40             if line.is_empty() {
41                 break;
42             }
43             if in_comment {
44                 if let Some(i) = line.find("*/") {
45                     line = &line[i + 2..];
46                     in_comment = false;
47                     continue;
48                 }
49             } else {
50                 let multi_idx = line.find("/*").unwrap_or_else(|| line.len());
51                 let single_idx = line.find("//").unwrap_or_else(|| line.len());
52                 code_in_line |= multi_idx > 0 && single_idx > 0;
53                 // Implies multi_idx is below line.len()
54                 if multi_idx < single_idx {
55                     line = &line[multi_idx + 2..];
56                     in_comment = true;
57                     continue;
58                 }
59             }
60             break;
61         }
62         if code_in_line {
63             line_count += 1;
64         }
65     }
66
67     if line_count > too_many_lines_threshold {
68         span_lint(
69             cx,
70             TOO_MANY_LINES,
71             span,
72             &format!(
73                 "this function has too many lines ({}/{})",
74                 line_count, too_many_lines_threshold
75             ),
76         );
77     }
78 }