summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs
new file mode 100644
index 000000000..54bdea7ea
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/functions/too_many_lines.rs
@@ -0,0 +1,87 @@
+use rustc_hir as hir;
+use rustc_hir::intravisit::FnKind;
+use rustc_lint::{LateContext, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_span::Span;
+
+use clippy_utils::diagnostics::span_lint;
+use clippy_utils::source::snippet_opt;
+
+use super::TOO_MANY_LINES;
+
+pub(super) fn check_fn(
+ cx: &LateContext<'_>,
+ kind: FnKind<'_>,
+ span: Span,
+ body: &hir::Body<'_>,
+ too_many_lines_threshold: u64,
+) {
+ // Closures must be contained in a parent body, which will be checked for `too_many_lines`.
+ // Don't check closures for `too_many_lines` to avoid duplicated lints.
+ if matches!(kind, FnKind::Closure) || in_external_macro(cx.sess(), span) {
+ return;
+ }
+
+ let code_snippet = match snippet_opt(cx, body.value.span) {
+ Some(s) => s,
+ _ => return,
+ };
+ let mut line_count: u64 = 0;
+ let mut in_comment = false;
+ let mut code_in_line;
+
+ let function_lines = if matches!(body.value.kind, hir::ExprKind::Block(..))
+ && code_snippet.as_bytes().first().copied() == Some(b'{')
+ && code_snippet.as_bytes().last().copied() == Some(b'}')
+ {
+ // Removing the braces from the enclosing block
+ &code_snippet[1..code_snippet.len() - 1]
+ } else {
+ &code_snippet
+ }
+ .trim() // Remove leading and trailing blank lines
+ .lines();
+
+ for mut line in function_lines {
+ code_in_line = false;
+ loop {
+ line = line.trim_start();
+ if line.is_empty() {
+ break;
+ }
+ if in_comment {
+ if let Some(i) = line.find("*/") {
+ line = &line[i + 2..];
+ in_comment = false;
+ continue;
+ }
+ } else {
+ let multi_idx = line.find("/*").unwrap_or(line.len());
+ let single_idx = line.find("//").unwrap_or(line.len());
+ code_in_line |= multi_idx > 0 && single_idx > 0;
+ // Implies multi_idx is below line.len()
+ if multi_idx < single_idx {
+ line = &line[multi_idx + 2..];
+ in_comment = true;
+ continue;
+ }
+ }
+ break;
+ }
+ if code_in_line {
+ line_count += 1;
+ }
+ }
+
+ if line_count > too_many_lines_threshold {
+ span_lint(
+ cx,
+ TOO_MANY_LINES,
+ span,
+ &format!(
+ "this function has too many lines ({}/{})",
+ line_count, too_many_lines_threshold
+ ),
+ );
+ }
+}