2 use rustc_hir::intravisit::FnKind;
3 use rustc_lint::{LateContext, LintContext};
4 use rustc_middle::lint::in_external_macro;
7 use clippy_utils::diagnostics::span_lint;
8 use clippy_utils::source::snippet_opt;
10 use super::TOO_MANY_LINES;
12 pub(super) fn check_fn(
16 body: &'tcx hir::Body<'_>,
17 too_many_lines_threshold: u64,
19 // Closures must be contained in a parent body, which will be checked for `too_many_lines`.
20 // Don't check closures for `too_many_lines` to avoid duplicated lints.
21 if matches!(kind, FnKind::Closure) || in_external_macro(cx.sess(), span) {
25 let code_snippet = match snippet_opt(cx, body.value.span) {
29 let mut line_count: u64 = 0;
30 let mut in_comment = false;
33 let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..))
34 && code_snippet.as_bytes().first().copied() == Some(b'{')
35 && code_snippet.as_bytes().last().copied() == Some(b'}')
37 // Removing the braces from the enclosing block
38 &code_snippet[1..code_snippet.len() - 1]
42 .trim() // Remove leading and trailing blank lines
45 for mut line in function_lines {
48 line = line.trim_start();
53 if let Some(i) = line.find("*/") {
54 line = &line[i + 2..];
59 let multi_idx = line.find("/*").unwrap_or_else(|| line.len());
60 let single_idx = line.find("//").unwrap_or_else(|| line.len());
61 code_in_line |= multi_idx > 0 && single_idx > 0;
62 // Implies multi_idx is below line.len()
63 if multi_idx < single_idx {
64 line = &line[multi_idx + 2..];
76 if line_count > too_many_lines_threshold {
82 "this function has too many lines ({}/{})",
83 line_count, too_many_lines_threshold