collector.ex (1718B)
1 defmodule Credo.Check.Consistency.ParameterPatternMatching.Collector do 2 @moduledoc false 3 4 use Credo.Check.Consistency.Collector 5 6 def collect_matches(source_file, _params) do 7 position_recorder = &record_position/4 8 9 Credo.Code.prewalk(source_file, &traverse(position_recorder, &1, &2), %{}) 10 end 11 12 def find_locations_not_matching(expected, source_file) do 13 location_recorder = &record_not_matching(expected, &1, &2, &3, &4) 14 15 source_file 16 |> Credo.Code.prewalk(&traverse(location_recorder, &1, &2), []) 17 |> Enum.reverse() 18 end 19 20 def actual_for(:before = _expected), do: :after 21 def actual_for(:after = _expected), do: :before 22 23 defp traverse(callback, {:def, _, [{_name, _, params}, _]} = ast, acc) 24 when is_list(params) do 25 {ast, traverse_params(callback, params, acc)} 26 end 27 28 defp traverse(callback, {:defp, _, [{_name, _, params}, _]} = ast, acc) 29 when is_list(params) do 30 {ast, traverse_params(callback, params, acc)} 31 end 32 33 defp traverse(_callback, ast, acc), do: {ast, acc} 34 35 defp traverse_params(callback, params, acc) do 36 Enum.reduce(params, acc, fn 37 {:=, _, [{capture_name, meta, nil}, _rhs]}, param_acc -> 38 callback.(:before, capture_name, meta, param_acc) 39 40 {:=, _, [_lhs, {capture_name, meta, nil}]}, param_acc -> 41 callback.(:after, capture_name, meta, param_acc) 42 43 _, param_acc -> 44 param_acc 45 end) 46 end 47 48 defp record_position(kind, _capture_name, _meta, acc) do 49 Map.update(acc, kind, 1, &(&1 + 1)) 50 end 51 52 defp record_not_matching(expected, actual, capture_name, meta, acc) do 53 if actual != expected do 54 [[line_no: meta[:line], trigger: capture_name] | acc] 55 else 56 acc 57 end 58 end 59 end