Current section
Files
Jump to
Current section
Files
lib/unnecessary_pattern_matching.ex
defmodule Nicene.UnnecessaryPatternMatching do
@moduledoc """
Check to ensure that we aren't doing any unnecessary pattern matching or using unnecessary
guard clauses for functions.
"""
@explanation [check: @moduledoc]
use Credo.Check, base_priority: :high, category: :design
alias Nicene.Traverse
@doc false
def run(source_file, params \\ []) do
issue_meta = IssueMeta.for(source_file, params)
single_definitions =
source_file
|> Credo.Code.prewalk(&Traverse.get_funs/2)
|> Enum.map(fn {_, name, arity, _} -> {name, arity} end)
|> Enum.reduce(%{}, fn fun, acc -> Map.update(acc, fun, 1, &(&1 + 1)) end)
|> Enum.filter(fn {{_, arity}, count} -> count == 1 and arity != 0 end)
|> Enum.map(&elem(&1, 0))
issue_fun = fn line_no, name -> issue_for(issue_meta, line_no, name) end
check_fun = fn _, name, arity, _, args ->
{name, arity} in single_definitions and pattern_matching?(args)
end
Credo.Code.prewalk(source_file, &Traverse.traverse(&1, &2, check_fun, issue_fun))
end
defp pattern_matching?(ast) do
Enum.any?(ast, fn
{op, _, _} -> op == :=
_ -> false
end)
end
defp issue_for(issue_meta, line_no, name) do
format_issue(issue_meta,
message: "Unnecessary pattern matching or guard clause detected",
line_no: line_no,
trigger: name
)
end
end