Skip to content

Commit

Permalink
fix: resolve issue with unused analyzer reporting false positives
Browse files Browse the repository at this point in the history
Earlier it sometimes could happen that the order in which the graph
traversal was happening could cause the issues with reporting some
functions as unused while these were in fact used within application.
This simplifies flow of the checker as well as it provide a more error
prone solution.
  • Loading branch information
hauleth committed Jun 15, 2023
1 parent fa55f8b commit 3b86630
Showing 1 changed file with 4 additions and 22 deletions.
26 changes: 4 additions & 22 deletions lib/mix_unused/analyzers/unused.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ defmodule MixUnused.Analyzers.Unused do
def analyze(data, possibly_uncalled) do
graph = Graph.new(type: :directed)

uncalled_funcs = MapSet.new(possibly_uncalled, fn {mfa, _} -> mfa end)

graph =
for {m, calls} <- data,
{mfa, %{caller: {f, a}}} <- calls,
Expand All @@ -18,30 +20,10 @@ defmodule MixUnused.Analyzers.Unused do
Graph.add_edge(acc, {m, f, a}, mfa)
end

called =
Graph.Reducers.Dfs.reduce(graph, MapSet.new(), fn v, acc ->
if v in acc do
{:halt, acc}
else
edges = Graph.edges(graph, v)

called? =
Enum.any?(edges, fn %{v1: caller} ->
caller in acc or
Enum.all?(possibly_uncalled, fn {mfa, _} ->
mfa != caller
end)
end)

acc = if called?, do: MapSet.put(acc, v), else: acc

{:next, acc}
end
end)

for {mfa, meta} = call <- possibly_uncalled,
not Map.get(meta.doc_meta, :export, false),
mfa not in called,
reaching = Graph.reaching_neighbors(graph, [mfa]),
Enum.all?(reaching, fn caller -> caller in uncalled_funcs end),
into: %{},
do: call
end
Expand Down

0 comments on commit 3b86630

Please sign in to comment.