AST-level diff between two versions of a MetaAST tree.
Unlike text diffs (which report line changes), this module understands tree structure and reports semantic changes: added functions, removed imports, modified bodies, renamed containers.
Primary use case: incremental re-indexing. When a file changes, only the entities that actually changed need re-embedding and re-insertion into dllb.
Usage
old_ast = Metastatic.parse!(old_source)
new_ast = Metastatic.parse!(new_source)
diff = Dllb.MetaAST.Diff.diff_trees(old_ast, new_ast)
# Entities needing re-indexing
diff.stale # [{:function_def, "process/2"}, ...]
# Entities to remove from index
diff.removed # [{:function_def, "old_helper/1"}]
Summary
Functions
Compare two MetaAST trees and produce a summary of structural changes.
Returns true if the diff contains no changes.
Returns names of entities that should be removed from the index.
Returns names of entities that need re-indexing (added + modified + renamed).
Types
@type ast_change() :: %{ kind: change_kind(), node_type: atom(), name: String.t(), line: non_neg_integer() | nil }
@type change_kind() :: :added | :removed | :modified | :renamed
@type diff_summary() :: %{ changes: [ast_change()], added: non_neg_integer(), removed: non_neg_integer(), modified: non_neg_integer(), renamed: non_neg_integer() }
Functions
@spec diff_trees(tuple(), tuple()) :: diff_summary()
Compare two MetaAST trees and produce a summary of structural changes.
Comparison is done at the "named entity" level — functions, containers, imports — matching the granularity at which dllb stores AST documents.
@spec empty?(diff_summary()) :: boolean()
Returns true if the diff contains no changes.
@spec removed_entities(diff_summary()) :: [String.t()]
Returns names of entities that should be removed from the index.
@spec stale_entities(diff_summary()) :: [String.t()]
Returns names of entities that need re-indexing (added + modified + renamed).