Adze.Deps (Adze v0.1.0)

Copy Markdown View Source

Intra-module call graph.

For each defmodule in a file, list every callable (def, defp, defmacro, defmacrop, defguard, defguardp, defdelegate) with which sibling callables it invokes by name + arity.

External calls (Foo.bar/0, Kernel.+/2) and variable refs are dropped: an edge is only emitted when the call site's {name, arity} matches a callable defined in the same module. Pipes are expanded before walking so x |> foo() is detected as foo/2, and &foo/2 captures count as edges too.

Default arguments

A def with default args has one graph node — the canonical (highest) arity. def foo(a, b \\ 1) produces one foo/2 node, not separate foo/1 + foo/2 nodes. Calls at either arity resolve to foo/2 so fan-in queries stay accurate; the synthetic foo/1 that Elixir auto-derives at compile time is not a separate implementation, so treating it as one would produce phantom self-loops on recursive default-arg defs.

Summary

Types

call()

@type call() :: {atom(), non_neg_integer()}

def_entry()

@type def_entry() :: %{
  name: atom(),
  arity: non_neg_integer(),
  kind: atom(),
  private: boolean(),
  range: %{start: pos_integer(), end: pos_integer()} | nil,
  calls: [call()]
}

Functions

deps(source, opts \\ [])

@spec deps(
  String.t(),
  keyword()
) :: {:ok, map()} | {:error, term()}

deps_file(path)

@spec deps_file(Path.t()) :: {:ok, map()} | {:error, term()}