Skip to main content

wowlab_tidy/languages/rust/rules/complexity/
large_fn_params.rs

1use ra_ap_syntax::ast::{self, HasName};
2
3use crate::{AstCtx, Example, Violation};
4
5#[rustfmt::skip]
6const EXAMPLES: &[Example] = &[
7    Example {
8        label: "few params",
9        code: "fn f(a: i32, b: i32) {}",
10        pass: true,
11    },
12    Example {
13        label: "too many params",
14        code: "fn f(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32) {}",
15        pass: false,
16    },
17    Example {
18        label: "self not counted",
19        code: "struct S;\nimpl S {\n    fn f(&self, a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) {}\n}",
20        pass: true,
21    },
22    Example {
23        label: "at threshold",
24        code: "fn f(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32) {}",
25        pass: true,
26    },
27];
28
29crate::ast_rule!(
30    large_fn_params,
31    "Flag functions with > threshold parameters.",
32    "Functions with many parameters are hard to call correctly. Group related params into a struct.",
33    Medium,
34    params { threshold: i64 = 6 },
35);
36
37fn check_large_fn_params(ctx: &AstCtx<'_>) -> Vec<Violation> {
38    let max_params = ctx
39        .file
40        .config
41        .get_usize("rust_large_fn_params", &PARAMS[0]);
42
43    ctx.nodes::<ast::Fn>()
44        .filter(|function| !ctx.is_in_test(function))
45        .filter_map(|function| {
46            let count = function.param_list()?.params().count();
47
48            (count > max_params).then(|| {
49                let name = function.name()?;
50
51                Some(ctx.violation(
52                    &name,
53                    format!("function `{name}` has {count} parameters (max {max_params})"),
54                ))
55            })?
56        })
57        .collect()
58}
59
60crate::tidy_ast_test!(check_large_fn_params, {
61    crate::example_tests!(EXAMPLES, check_large_fn_params);
62});