Package: org.apache.groovy.contracts

## [Java] Class VariantSupport

- org.apache.groovy.contracts.VariantSupport

-     public final class VariantSupport
      extends Object

  Shared runtime support for Decreases termination measures, used by both the loop variant (`@Decreases` on a loop) and the recursion variant (`@Decreases` on a method, via MethodVariantSupport).

  It is the single source of truth for what "strictly decreases and stays well-founded" means — a scalar Comparable (with a non-negative floor for Numbers) or a List compared lexicographically — and for whether the check runs at all under the `-ea`/`-da` configuration. The comparison itself is violation-agnostic (describeFailure returns a description rather than throwing) so each caller can raise the appropriate violation type.

  Since:
    6.0.0

- - ### Methods Summary

    Methods
    Type Params | Return Type | Name and description
    --- | --- | ---
    `` | `public static void` | `checkLoopVariant(Object prev, Object curr, String className)` Loop-variant entry point invoked from generated loop-body code: if enabled, verify `curr` strictly decreased from `prev` and stayed well-founded, throwing LoopVariantViolation otherwise.
    `` | `public static void` | `checkLoopVariantEntry(Object curr, String className)` Loop-variant entry point for the first iteration of a loop, where no previous value exists to compare against: if enabled, verify a scalar Number measure is non-negative at loop entry (GROOVY-12128), throwing LoopVariantViolation otherwise.
    `` | `public static String` | `describeFailure(Object prev, Object curr)` Describe how `curr` fails to be a valid strict, well-founded decrease from `prev`, or `null` if it is valid.
    `` | `public static boolean` | `enabled(String className)` Whether termination-measure checks are enabled for `className` under the current `-ea`/`-da` configuration (a `null` class name uses the global default).

  - ### Inherited Methods Summary

    Inherited Methods
    Methods inherited from class | Name
    --- | ---
    `class Object` | `equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Method Detail

    - #### public static void checkLoopVariant(Object prev, Object curr, String className)

      Loop-variant entry point invoked from generated loop-body code: if enabled, verify `curr` strictly decreased from `prev` and stayed well-founded, throwing LoopVariantViolation otherwise.

      Parameters:
        `prev` - the variant before the iteration
        `curr` - the variant after the iteration
        `className` - the enclosing class name (for `-ea`/`-da` gating)

    - #### public static void checkLoopVariantEntry(Object curr, String className)

      Loop-variant entry point for the first iteration of a loop, where no previous value exists to compare against: if enabled, verify a scalar Number measure is non-negative at loop entry (GROOVY-12128), throwing LoopVariantViolation otherwise. This mirrors the non-negative floor describeFailure applies to every subsequent iteration-start value. List (lexicographic) measures have no single deciding component at entry, so they are not floor-checked here.

      Parameters:
        `curr` - the variant at first loop entry
        `className` - the enclosing class name (for `-ea`/`-da` gating)

    - #### public static String describeFailure(Object prev, Object curr)

      Describe how `curr` fails to be a valid strict, well-founded decrease from `prev`, or `null` if it is valid. List measures are compared lexicographically.

      Parameters:
        `prev` - the measure before
        `curr` - the measure after
      Returns:
        a failure description suffix, or `null` if the decrease is valid

    - #### public static boolean enabled(String className)

      Whether termination-measure checks are enabled for `className` under the current `-ea`/`-da` configuration (a `null` class name uses the global default). Mirrors how `@Requires`/`@Ensures` gate.

      Parameters:
        `className` - the enclosing class name, or `null` for the global default
      Returns:
        `true` if the check should run