defmodule Credo.Code.Parameters do @moduledoc """ This module provides helper functions to analyse the parameters taken by a function. """ @def_ops [:def, :defp, :defmacro] @doc "Returns the parameter count for the given function's AST" def count(nil), do: 0 for op <- @def_ops do def count({unquote(op), _, arguments}) when is_list(arguments) do case arguments |> List.first do {_atom, _meta, nil} -> 0 {_atom, _meta, list} -> list |> Enum.count _ -> 0 end end end @doc "Returns the names of parameters for the given function's AST" def names(nil), do: nil for op <- @def_ops do def names({unquote(op), _meta, arguments}) when is_list(arguments) do arguments |> List.first |> get_param_names end end defp get_param_names({:when, _meta, arguments}) do arguments |> List.first |> get_param_names end defp get_param_names(arguments) when is_tuple(arguments) do arguments |> Tuple.to_list |> List.last |> Enum.map(&get_param_name/1) |> Enum.reject(&is_nil/1) end defp get_param_name({:::, _, [var, _type]}) do var |> get_param_name end defp get_param_name({:<<>>, _, arguments}) do arguments |> Enum.map(&get_param_name/1) |> Enum.reject(&is_nil/1) end defp get_param_name({:=, _, arguments}) do arguments |> Enum.map(&get_param_name/1) |> Enum.reject(&is_nil/1) end defp get_param_name({:%, _, [{:__aliases__, _meta, _mod_list}, {:%{}, _meta2, arguments}]}) do arguments |> get_param_name end defp get_param_name({:%{}, _, arguments}) do arguments |> get_param_name end defp get_param_name({:\\, _, arguments}) do arguments |> Enum.find_value(&get_param_name/1) end defp get_param_name(list) when is_list(list) do list |> Enum.map(fn {atom, tuple} when is_atom(atom) and is_tuple(tuple) -> get_param_name(tuple) end) |> Enum.reject(&is_nil/1) end defp get_param_name({name, _, nil}) when is_atom(name), do: name defp get_param_name(_) do nil end end