Metastatic.Analysis.UnusedVariables
(Metastatic v0.10.4)
View Source
Unused variable detection at the MetaAST level.
Identifies variables that are assigned but never read, including function parameters, loop iterators, and pattern matches. Works across all supported languages by operating on the unified MetaAST representation.
This module implements both:
- Standalone API - Direct analysis via
analyze/2returning structured results - Analyzer behaviour - Plugin integration for batch analysis via Runner
Detection Categories
- Local variables - Assigned but never referenced
- Function parameters - Lambda parameters never used in body
- Loop iterators - Loop variables never accessed
- Pattern matches - Variables bound in patterns but not used
Standalone Usage
alias Metastatic.{Document, Analysis.UnusedVariables}
# Analyze for unused variables
ast = {:block, [], [
{:assignment, [], [{:variable, [], "x"}, {:literal, [subtype: :integer], 42}]},
{:literal, [subtype: :integer], 5}
]}
doc = Document.new(ast, :python)
{:ok, result} = UnusedVariables.analyze(doc)
result.has_unused? # => true
result.total_unused # => 1
result.unused_variables # => [%{name: "x", category: :local, ...}]Plugin Usage
alias Metastatic.Analysis.{Registry, Runner}
# Register as analyzer plugin
Registry.register(UnusedVariables)
# Run via Runner
{:ok, report} = Runner.run(doc)Configuration (when used as plugin)
:ignore_prefix- Ignore variables starting with this prefix (default:"_"):ignore_names- List of variable names to ignore (default:[])
Examples
# No unused variables
iex> ast = {:assignment, [], [{:variable, [], "x"}, {:literal, [subtype: :integer], 5}]}
iex> doc = Metastatic.Document.new(ast, :python)
iex> {:ok, result} = Metastatic.Analysis.UnusedVariables.analyze(doc)
iex> result.has_unused?
false
# Unused local variable
iex> ast = {:block, [], [
...> {:assignment, [], [{:variable, [], "x"}, {:literal, [subtype: :integer], 1}]},
...> {:literal, [subtype: :integer], 2}
...> ]}
iex> doc = Metastatic.Document.new(ast, :python)
iex> {:ok, result} = Metastatic.Analysis.UnusedVariables.analyze(doc)
iex> result.has_unused?
true
iex> [var | _] = result.unused_variables
iex> var.name
"x"
iex> var.category
:local
Summary
Functions
@spec analyze(Metastatic.language(), term(), keyword()) :: {:ok, map()} | {:error, term()}
Analyzes a document for unused variables.
Returns {:ok, result} where result is a Metastatic.Analysis.UnusedVariables.Result struct.
Options
:ignore_underscore- Ignore variables starting with underscore (default: true):categories- List of categories to check (default: all)
Examples
iex> ast = {:literal, [subtype: :integer], 42}
iex> doc = Metastatic.Document.new(ast, :elixir)
iex> {:ok, result} = Metastatic.Analysis.UnusedVariables.analyze(doc)
iex> result.has_unused?
false
@spec analyze!(Metastatic.language(), term(), keyword()) :: map()
Analyzes a document for unused variables.
Returns {:ok, result} where result is a Metastatic.Analysis.UnusedVariables.Result struct.
Options
:ignore_underscore- Ignore variables starting with underscore (default: true):categories- List of categories to check (default: all)
Examples
iex> ast = {:literal, [subtype: :integer], 42}
iex> doc = Metastatic.Document.new(ast, :elixir)
iex> {:ok, result} = Metastatic.Analysis.UnusedVariables.analyze(doc)
iex> result.has_unused?
falseUnlike not-banged version, this one either returns a result or raises