wowlab_tidy/languages/rust/rules/complexity/
large_fn_params.rs1use 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});