Search documentation of Metastatic

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

View Source

Code complexity analysis at the MetaAST level.

Analyzes code to compute comprehensive complexity metrics that work uniformly across all supported languages by operating on the unified MetaAST representation.

## Metrics

- Cyclomatic Complexity - McCabe metric, decision points + 1
- Cognitive Complexity - Structural complexity with nesting penalties
- Nesting Depth - Maximum nesting level
- Halstead Metrics - Volume, difficulty, effort
- Lines of Code - Physical, logical, comments
- Function Metrics - Statements, returns, variables

## Usage

    alias Metastatic.{Document, Analysis.Complexity}

    # Analyze a document
    ast = {:conditional, [], [
      {:variable, [], "x"},
      {:literal, [subtype: :integer], 1},
      {:literal, [subtype: :integer], 2}]}
    doc = Document.new(ast, :python)
    {:ok, result} = Complexity.analyze(doc)

    result.cyclomatic       # => 2
    result.cognitive        # => 1
    result.max_nesting      # => 1
    result.warnings         # => []
    result.summary          # => "Code has low complexity"

## Options

- `:thresholds` - Configurable threshold map (see `Metastatic.Analysis.Complexity.Result`)
- `:metrics` - List of metrics to calculate (default: all)

## Examples

    # Simple arithmetic: complexity = 1
    iex> ast = {:binary_op, [category: :arithmetic, operator: :+], [{:literal, [subtype: :integer], 1}, {:literal, [subtype: :integer], 2}]}
    iex> doc = Metastatic.Document.new(ast, :python)
    iex> {:ok, result} = Metastatic.Analysis.Complexity.analyze(doc)
    iex> result.cyclomatic
    1

    # Conditional: complexity = 2
    iex> ast = {:conditional, [], [
    ...>   {:variable, [], "x"},
    ...>   {:literal, [subtype: :integer], 1},
    ...>   {:literal, [subtype: :integer], 2}]}
    iex> doc = Metastatic.Document.new(ast, :elixir)
    iex> {:ok, result} = Metastatic.Analysis.Complexity.analyze(doc)
    iex> result.cyclomatic
    2

## Summary

### Functions

analyze(doc)

Analyzes a document for complexity.

analyze!(doc)

Analyzes a document for complexity.

## Functions

# analyze(doc)

    @spec analyze(Metastatic.Document.t()) :: {:ok, term()} | {:error, term()}

Analyzes a document for complexity.

Accepts either:

- A `Metastatic.Document` struct
- A `{language, native_ast}` tuple

Returns `{:ok, result}` where result is a `Metastatic.Analysis.Complexity.Result` struct.

## Options

- `:thresholds` - Threshold map for warnings (default thresholds used if not provided)
- `:metrics` - List of metrics to calculate (default: `:all`)

## Examples

    # Using Document
    iex> ast = {:literal, [subtype: :integer], 42}
    iex> doc = Metastatic.Document.new(ast, :python)
    iex> {:ok, result} = Metastatic.Analysis.Complexity.analyze(doc)
    iex> result.cyclomatic
    1
    iex> result.cognitive
    0

    # Using {language, native_ast} tuple
    iex> python_ast = %{"_type" => "Constant", "value" => 42}
    iex> {:ok, result} = Metastatic.Analysis.Complexity.analyze(:python, python_ast, [])
    iex> result.cyclomatic
    1

# analyze!(doc)

    @spec analyze!(Metastatic.Document.t()) :: term()

Analyzes a document for complexity.

Accepts either:

- A `Metastatic.Document` struct
- A `{language, native_ast}` tuple

Returns `{:ok, result}` where result is a `Metastatic.Analysis.Complexity.Result` struct.

## Options

- `:thresholds` - Threshold map for warnings (default thresholds used if not provided)
- `:metrics` - List of metrics to calculate (default: `:all`)

## Examples

    # Using Document
    iex> ast = {:literal, [subtype: :integer], 42}
    iex> doc = Metastatic.Document.new(ast, :python)
    iex> {:ok, result} = Metastatic.Analysis.Complexity.analyze(doc)
    iex> result.cyclomatic
    1
    iex> result.cognitive
    0

    # Using {language, native_ast} tuple
    iex> python_ast = %{"_type" => "Constant", "value" => 42}
    iex> {:ok, result} = Metastatic.Analysis.Complexity.analyze(:python, python_ast, [])
    iex> result.cyclomatic
    1

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