Metastatic.Analysis.Complexity.Cognitive (Metastatic v0.10.4)

View Source

Cognitive complexity calculation.

Cognitive complexity measures how difficult code is to understand, taking into account nested structures that increase the mental burden on readers.

3-Tuple Format

All MetaAST nodes use the uniform 3-tuple structure: {type_atom, keyword_meta, children_or_value}

Algorithm

Based on the Sonar cognitive complexity specification:

  • Base Increments: Structural elements add to complexity

    • conditional - +1 (+nesting level)
    • loop - +1 (+nesting level)
    • binary_op with :boolean and :and/:or - +1
    • pattern_match - +1 (+nesting level per branch)
    • exception_handling - +1 (+nesting level)
  • Nesting Penalty: Each level of nesting adds to the increment

    • Conditional at level 0: +1
    • Conditional at level 1: +2
    • Conditional at level 2: +3

Difference from Cyclomatic

Cognitive complexity differs from cyclomatic in that it:

  • Applies nesting penalties (deeper = more complex)
  • Doesn't count boolean operators in conditions the same way
  • Emphasizes understandability over testability

Examples

# Simple conditional: cognitive = 1
iex> ast = {:conditional, [], [{:variable, [], "x"}, {:literal, [subtype: :integer], 1}, {:literal, [subtype: :integer], 2}]}
iex> Metastatic.Analysis.Complexity.Cognitive.calculate(ast)
1

# Nested conditional: cognitive = 3 (1 + 2)
iex> ast = {:conditional, [], [
...>   {:variable, [], "x"},
...>   {:conditional, [], [{:variable, [], "y"}, {:literal, [subtype: :integer], 1}, {:literal, [subtype: :integer], 2}]},
...>   {:literal, [subtype: :integer], 3}]}
iex> Metastatic.Analysis.Complexity.Cognitive.calculate(ast)
3

Summary

Functions

Calculates cognitive complexity for a MetaAST node.

Functions

calculate(ast)

@spec calculate(Metastatic.AST.meta_ast()) :: non_neg_integer()

Calculates cognitive complexity for a MetaAST node.

Returns the complexity as a non-negative integer (minimum 0).

Examples

iex> ast = {:literal, [subtype: :integer], 42}
iex> Metastatic.Analysis.Complexity.Cognitive.calculate(ast)
0

iex> ast = {:conditional, [], [
...>   {:variable, [], "x"},
...>   {:literal, [subtype: :integer], 1},
...>   {:literal, [subtype: :integer], 2}]}
iex> Metastatic.Analysis.Complexity.Cognitive.calculate(ast)
1