defmodule TallariumCredo.Checks.Destructure do @moduledoc """ Encourages the use of Destructure """ use Credo.Check, base_priority: :normal, category: :consistency, explanations: [ check: """ Use Destructure and the d(%{}) macro to destructure maps. """ ] import Destructure @doc false @impl true def run(source_file, params \\ []) do issue_meta = IssueMeta.for(source_file, params) initial_state = d(%{issue_meta, issues: []}) d(%{issues}) = Credo.Code.prewalk(source_file, &traverse/2, initial_state) issues end defp traverse({:%{}, meta, args} = ast, state) do if is_destructure_expression?(args) do issues = state.issues ++ [issue_for(state.issue_meta, meta[:line])] {ast, %{state | issues: issues}} else {ast, state} end end defp traverse(ast, state) do {ast, state} end defp is_destructure_expression?(args) do Keyword.keyword?(args) && Enum.count(args, &is_destructure_variable?/1) > 1 end defp is_destructure_variable?(arg) do case arg do {key, {key, _, nil}} -> true _ -> false end end defp issue_for(issue_meta, line_no) do format_issue(issue_meta, message: "d(%{}) should be used instead of %{}", line_no: line_no ) end end