Metastatic.Semantic.Callbacks.ElixirResolver (Metastatic v0.22.2)

View Source

Resolves Elixir use macros to discover which behaviours they inject.

When use SomeModule appears inside a container, this resolver figures out which @behaviour attributes that use directive introduces, so that the enricher can annotate callback implementations.

Two resolution strategies are tried in order:

  1. Runtime query (fast path): If the target module is compiled and loaded, expand use Module via ExPanda and scan the expanded AST for @behaviour attributes.

  2. ExPanda expansion (slow path): For source-only modules, expand the use call via ExPanda.expand/1 and scan the resulting AST.

Results are cached in :persistent_term to avoid re-expansion.

Integration

The enricher calls resolve_behaviours/1 when it encounters an :import node with import_type: :use inside an Elixir container. Discovered behaviours are dynamically registered in the Semantic.Callbacks registry.

Summary

Types

A resolved behaviour: the module name string

Functions

Clears the resolution cache. Primarily for testing.

Resolves which behaviours a use Module directive introduces.

Types

behaviour_name()

@type behaviour_name() :: String.t()

A resolved behaviour: the module name string

Functions

clear_cache()

@spec clear_cache() :: :ok

Clears the resolution cache. Primarily for testing.

resolve_behaviours(module_name)

@spec resolve_behaviours(String.t()) :: [behaviour_name()]

Resolves which behaviours a use Module directive introduces.

Returns a list of behaviour module name strings (e.g., ["GenServer"]). For each discovered behaviour that defines callbacks, the callbacks are automatically registered in the Semantic.Callbacks registry.

Examples

iex> behaviours = ElixirResolver.resolve_behaviours("GenServer")
iex> "GenServer" in behaviours
true

iex> ElixirResolver.resolve_behaviours("SomeUnknownModule")
[]