Here's an example on how to do it.
defmodule OneUseAlone do
use Credo.Check,
base_priority: :high,
category: :warning,
explanations: [
check: """
Checks if `use` happens more than once in a given module
"""
]
@impl Credo.Check
def run(source_file, params) do
issue_meta = Credo.IssueMeta.for(source_file, params)
Credo.Code.prewalk(source_file, &walk(&1, &2, issue_meta))
end
defp walk(ast, issues, issue_meta) do
case(ast) do
{:defmodule, _meta, _children} ->
new_issues =
ast
|> Credo.Code.prewalk(&collect/2)
|> report(issue_meta)
{ast, issues ++ new_issues}
_other ->
{ast, issues}
end
end
defp collect(ast, acc) do
case(ast) do
{:use, _meta, [{:__aliases__, meta, module}]} ->
{ast, acc ++ [{module, meta[:line]}]}
# Reset on submodules
{:defmodule, _meta, _children} when length(acc) < 2 ->
{ast, []}
_other ->
{ast, acc}
end
end
defp report(uses, issue_meta) do
if length(uses) < 2 do
[]
else
[
format_issue(
issue_meta,
message: "`use ...` appears more than once in the module"
)
]
end
end
end