Current section

Files

Jump to
nicene lib public_functions_first.ex
Raw

lib/public_functions_first.ex

defmodule Nicene.PublicFunctionsFirst do
@moduledoc """
Public functions in a module should be defined before private functions.
"""
@explanation [check: @moduledoc]
use Credo.Check, base_priority: :high, category: :readability
alias Nicene.Traverse
@doc false
def run(source_file, params \\ []) do
case Credo.Code.prewalk(source_file, &Traverse.get_funs/2) do
[] ->
[]
functions ->
issue_meta = IssueMeta.for(source_file, params)
functions
|> Enum.max_by(fn
{:def, _, _, line_no} -> line_no
_ -> 0
end)
|> case do
{:defp, _, _, _} ->
[]
{_, _, _, last_public_function} ->
Enum.reduce(
functions,
[],
&check_function(&1, &2, issue_meta, last_public_function)
)
end
end
end
defp check_function({:defp, _, _, line}, issues, issue_meta, public_line)
when line < public_line do
[issue_for(issue_meta, line) | issues]
end
defp check_function(_, issues, _, _), do: issues
defp issue_for(issue_meta, line_no) do
format_issue(issue_meta,
message: "Private function is defined before a public function",
line_no: line_no
)
end
end