ArchTest.Collector (ArchTest v0.3.1)

Copy Markdown View Source

Builds a module dependency graph using OTP's :xref tool.

The graph is a map of %{caller_module => [callee_module]} derived from BEAM files. Results are cached in :persistent_term for the duration of the test run.

No external dependencies are required — :xref and :beam_lib are standard OTP applications.

Summary

Functions

Returns all modules known in the graph.

Returns the dependency graph for the given OTP application (or all loaded modules if app is :all).

Builds a dependency graph from a specific BEAM directory path.

Builds a dependency graph from one or more BEAM directory paths.

Returns function-level call metadata for the given OTP application.

Returns function-level call metadata from a BEAM directory path.

Returns function-level call metadata from one or more BEAM directory paths.

Returns all dependency cycles found in the given modules.

Returns the direct dependencies of module (modules it calls).

Returns all modules that directly depend on module (callers of it).

Computes transitive dependencies of module up to max_depth hops (default: unlimited).

Types

graph()

@type graph() :: %{required(module()) => [module()]}

Functions

all_modules(graph)

@spec all_modules(graph()) :: [module()]

Returns all modules known in the graph.

build_graph(app \\ :all, opts \\ [])

@spec build_graph(
  atom() | :all,
  keyword()
) :: graph()

Returns the dependency graph for the given OTP application (or all loaded modules if app is :all).

The graph is cached in :persistent_term after the first call. Pass force: true to bypass the cache and rebuild.

Options

  • :app — OTP app atom or :all (default :all)
  • :apps — list of OTP apps to inspect together
  • :paths — BEAM ebin path or paths to inspect instead of an app
  • :include — list of module glob patterns to keep
  • :exclude — list of module glob patterns to remove
  • :force — boolean, bypass cache (default false)

build_graph_from_path(ebin_path, opts \\ [])

@spec build_graph_from_path(
  String.t(),
  keyword()
) :: graph()

Builds a dependency graph from a specific BEAM directory path.

Useful for testing against a pre-compiled application without registering it as an OTP application.

Options

  • :force — boolean, bypass cache (default false)

Example

ebin = "test/support/fixture_app/_build/dev/lib/fixture_app/ebin"
graph = ArchTest.Collector.build_graph_from_path(ebin)

build_graph_from_paths(paths, opts \\ [])

@spec build_graph_from_paths(
  String.t() | [String.t()],
  keyword()
) :: graph()

Builds a dependency graph from one or more BEAM directory paths.

Options:

  • :force — bypass cache
  • :include — list of module glob patterns to keep
  • :exclude — list of module glob patterns to remove

calls(app \\ :all, opts \\ [])

@spec calls(
  atom() | :all,
  keyword()
) :: [ArchTest.Call.t()]

Returns function-level call metadata for the given OTP application.

Requires BEAM files compiled with debug info. Missing debug info yields an empty call list for that module rather than an exception.

Accepts the same scope and filter options as build_graph/2: :apps, :paths, :include, :exclude, and :force. Compiler-generated metadata calls are omitted. Remote captures and static apply/3 calls are reported when debug information exposes them.

calls_from_path(path, opts \\ [])

@spec calls_from_path(
  String.t(),
  keyword()
) :: [ArchTest.Call.t()]

Returns function-level call metadata from a BEAM directory path.

calls_from_paths(paths, opts \\ [])

@spec calls_from_paths(
  String.t() | [String.t()],
  keyword()
) :: [ArchTest.Call.t()]

Returns function-level call metadata from one or more BEAM directory paths.

Options:

  • :force — bypass cache
  • :include — list of caller/callee module glob patterns to keep
  • :exclude — list of caller/callee module glob patterns to remove

cycles(graph)

@spec cycles(graph()) :: [[module()]]

Returns all dependency cycles found in the given modules.

Each cycle is a list of modules forming a circular dependency chain.

dependencies_of(graph, module)

@spec dependencies_of(graph(), module()) :: [module()]

Returns the direct dependencies of module (modules it calls).

dependents_of(graph, target)

@spec dependents_of(graph(), module()) :: [module()]

Returns all modules that directly depend on module (callers of it).

transitive_dependencies_of(graph, module, max_depth \\ :infinity)

@spec transitive_dependencies_of(graph(), module(), pos_integer() | :infinity) :: [
  module()
]

Computes transitive dependencies of module up to max_depth hops (default: unlimited).