function_arity.ex (2201B)
1 defmodule Credo.Check.Refactor.FunctionArity do 2 use Credo.Check, 3 param_defaults: [max_arity: 8, ignore_defp: false], 4 explanations: [ 5 check: """ 6 A function can take as many parameters as needed, but even in a functional 7 language there can be too many parameters. 8 9 Can optionally ignore private functions (check configuration options). 10 """, 11 params: [ 12 max_arity: "The maximum number of parameters which a function should take.", 13 ignore_defp: "Set to `true` to ignore private functions." 14 ] 15 ] 16 17 alias Credo.Code.Parameters 18 19 @def_ops [:def, :defp, :defmacro] 20 21 @doc false 22 @impl true 23 def run(%SourceFile{} = source_file, params) do 24 issue_meta = IssueMeta.for(source_file, params) 25 max_arity = Params.get(params, :max_arity, __MODULE__) 26 ignore_defp = Params.get(params, :ignore_defp, __MODULE__) 27 28 Credo.Code.prewalk( 29 source_file, 30 &traverse(&1, &2, issue_meta, max_arity, ignore_defp) 31 ) 32 end 33 34 # TODO: consider for experimental check front-loader (ast) 35 for op <- @def_ops do 36 defp traverse( 37 {unquote(op) = op, meta, arguments} = ast, 38 issues, 39 issue_meta, 40 max_arity, 41 ignore_defp 42 ) 43 when is_list(arguments) do 44 arity = Parameters.count(ast) 45 46 if issue?(op, ignore_defp, arity, max_arity) do 47 fun_name = Credo.Code.Module.def_name(ast) 48 49 { 50 ast, 51 issues ++ [issue_for(issue_meta, meta[:line], fun_name, max_arity, arity)] 52 } 53 else 54 {ast, issues} 55 end 56 end 57 end 58 59 defp traverse(ast, issues, _issue_meta, _max_arity, _ignore_defp) do 60 {ast, issues} 61 end 62 63 defp issue?(:defp, true, _, _), do: false 64 defp issue?(_, _, arity, max_arity) when arity > max_arity, do: true 65 defp issue?(_, _, _, _), do: false 66 67 defp issue_for(issue_meta, line_no, trigger, max_value, actual_value) do 68 format_issue( 69 issue_meta, 70 message: 71 "Function takes too many parameters (arity is #{actual_value}, max is #{max_value}).", 72 trigger: trigger, 73 line_no: line_no, 74 severity: Severity.compute(actual_value, max_value) 75 ) 76 end 77 end