Metastatic.Semantic.Enricher
(Metastatic v0.10.4)
View Source
AST enricher for semantic metadata injection.
This module provides functions to enrich MetaAST nodes with semantic
operation metadata (op_kind). It is designed to be called during
adapter transformations (in to_meta) to eagerly annotate function
calls with their semantic meaning.
Usage
Single Node Enrichment
alias Metastatic.Semantic.Enricher
# Enrich a single function_call node
enriched = Enricher.enrich(node, :elixir)Full Tree Enrichment
# Enrich all nodes in an AST tree
enriched_ast = Enricher.enrich_tree(ast, :python)Integration with Adapters
The enricher should be called at the end of the to_meta transformation:
def transform(native_ast) do
with {:ok, meta_ast, metadata} <- do_transform(native_ast) do
enriched = Enricher.enrich_tree(meta_ast, :python)
{:ok, enriched, metadata}
end
endEnrichment Strategy
Enrichment is eager - all applicable nodes are enriched in a single pass. This ensures semantic information is available immediately for analyzers.
Only :function_call nodes are currently enriched. The enricher:
- Extracts the function name from metadata
- Matches against registered patterns for the source language
- If matched, adds
op_kindto the node's metadata - Extracts target entity from arguments when possible
Summary
Types
Language identifier for pattern matching
Functions
Enriches a single MetaAST node with semantic metadata.
Enriches an entire AST tree with semantic metadata.
Checks if a node has been enriched with semantic metadata.
Gets the op_kind from a node, if present.
Types
@type language() :: Metastatic.Semantic.Patterns.language()
Language identifier for pattern matching
Functions
@spec enrich(Metastatic.AST.meta_ast(), language()) :: Metastatic.AST.meta_ast()
Enriches a single MetaAST node with semantic metadata.
If the node is a :function_call and matches a known pattern for the
given language, adds op_kind metadata. Otherwise returns the node unchanged.
Parameters
node- The MetaAST node to enrichlanguage- The source language for pattern matching
Examples
iex> node = {:function_call, [name: "Repo.get"], [{:variable, [], "User"}, {:literal, [subtype: :integer], 1}]}
iex> enriched = Enricher.enrich(node, :elixir)
iex> Keyword.get(elem(enriched, 1), :op_kind)
[domain: :db, operation: :retrieve, target: "User", async: false, framework: :ecto]
@spec enrich_tree(Metastatic.AST.meta_ast(), language()) :: Metastatic.AST.meta_ast()
Enriches an entire AST tree with semantic metadata.
Traverses the AST and enriches all applicable nodes. This is the recommended way to enrich AST during adapter transformations.
Parameters
ast- The root MetaAST nodelanguage- The source language for pattern matching
Examples
iex> ast = {:block, [], [
...> {:function_call, [name: "Repo.get"], [{:variable, [], "User"}, {:literal, [subtype: :integer], 1}]},
...> {:function_call, [name: "Repo.all"], [{:variable, [], "Post"}]}
...> ]}
iex> enriched = Enricher.enrich_tree(ast, :elixir)
iex> {:block, [], [call1, call2]} = enriched
iex> Keyword.get(elem(call1, 1), :op_kind) |> Keyword.get(:operation)
:retrieve
iex> Keyword.get(elem(call2, 1), :op_kind) |> Keyword.get(:operation)
:retrieve_all
@spec enriched?(Metastatic.AST.meta_ast()) :: boolean()
Checks if a node has been enriched with semantic metadata.
Examples
iex> node = {:function_call, [name: "Repo.get", op_kind: [domain: :db, operation: :retrieve]], []}
iex> Enricher.enriched?(node)
true
iex> node = {:function_call, [name: "unknown"], []}
iex> Enricher.enriched?(node)
false
@spec get_op_kind(Metastatic.AST.meta_ast()) :: Metastatic.Semantic.OpKind.t() | nil
Gets the op_kind from a node, if present.
Examples
iex> node = {:function_call, [name: "Repo.get", op_kind: [domain: :db, operation: :retrieve]], []}
iex> Enricher.get_op_kind(node)
[domain: :db, operation: :retrieve]
iex> node = {:function_call, [name: "unknown"], []}
iex> Enricher.get_op_kind(node)
nil