Search documentation of Metastatic

# Metastatic.Analysis.UnusedVariables (Metastatic v0.13.2)

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/2` returning 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

analyze(doc)

Analyzes a document for unused variables.

analyze!(doc)

Analyzes a document for unused variables.

info()

## Functions

# analyze(doc)

    @spec analyze(Metastatic.Document.t()) :: {:ok, term()} | {: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

# analyze!(doc)

    @spec analyze!(Metastatic.Document.t()) :: 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

Unlike not-banged version, this one either returns a result or raises

# info()