Package org.codehaus.groovy.ast.tools

# Class GenericsUtils

java.lang.Object
org.codehaus.groovy.ast.tools.GenericsUtils

public class GenericsUtils extends Object
Utility methods for working with parameterized (generic) types in Groovy AST.

Provides comprehensive support for generic type operations including:

- Type parameter extraction and alignment
- Wildcard type construction and handling
- Generic type specification creation and resolution
- Inheritance hierarchy generic type parameterization
- Type compatibility and assignability checks with generics

Used extensively in static type checking, method resolution, and AST transformation to properly handle Java generic type syntax in Groovy code.

See Also:
  - `for type parameter/argument representation`
  - `for class information with generics`
  - `for related class utilities`

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `static final GenericsType[]`
  `EMPTY_GENERICS_ARRAY`
  An empty array of generic type arguments, used as a constant to avoid repeated allocations.
  `static final String`
  `JAVA_LANG_OBJECT`
  Canonical string representation of `java.lang.Object`.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `GenericsUtils()`

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static Map<String,ClassNode>`
  `addMethodGenerics(MethodNode node, Map<String,ClassNode> oldSpec)`
  `static GenericsType[]`
  `alignGenericTypes(GenericsType[] redirectGenericTypes, GenericsType[] parameterizedTypes, GenericsType[] alignmentTarget)`
  Deprecated, for removal: This API element is subject to removal in a future version.
  You shouldn't call this method because it is inherently unreliable.
  `static GenericsType[]`
  `applyGenericsContextToPlaceHolders(Map<String,ClassNode> genericsSpec, GenericsType[] oldPlaceHolders)`
  Transforms generics types from an old context to a new context using the given spec.
  `static void`
  `applyGenericsSpec(ClassNode type, Map<String,ClassNode> genericsSpec)`
  Writes `genericsSpec` onto `type` as an explicit type-argument list, filling any missing parameter from its bound (or `Object`).
  `static GenericsType`
  `buildWildcardType(ClassNode... upperBounds)`
  Generates a wildcard generic type in order to be used for checks against class nodes.
  `static void`
  `clearParameterizedTypeCache()`
  Clears the parameterized type cache.
  `static ClassNode`
  `correctToGenericsSpec(Map<String,ClassNode> genericsSpec, ClassNode type)`
  `static ClassNode`
  `correctToGenericsSpec(Map<String,ClassNode> genericsSpec, GenericsType type)`
  `static MethodNode`
  `correctToGenericsSpec(Map<String,ClassNode> genericsSpec, MethodNode mn)`
  `static ClassNode`
  `correctToGenericsSpecRecurse(Map<String,ClassNode> genericsSpec, ClassNode type)`
  `static ClassNode[]`
  `correctToGenericsSpecRecurse(Map<String,ClassNode> genericsSpec, ClassNode[] types)`
  `static ClassNode`
  `correctToGenericsSpecRecurse(Map<String,ClassNode> genericsSpec, ClassNode type, List<String> exclusions)`
  `static Map<String,ClassNode>`
  `createGenericsSpec(ClassNode type)`
  `static Map<String,ClassNode>`
  `createGenericsSpec(ClassNode type, Map<String,ClassNode> oldSpec)`
  `static ClassNode`
  `diamondTargetOfAnonymousClass(ClassNode anonType)`
  Diamond `<>` of an anonymous class is stored on its super type, or on an interface once `InnerClassVisitor` has moved an interface super type.
  `static ClassNode`
  `erasure(ClassNode type)`
  Computes the erasure of a type, safe to declare in a generated signature that cannot carry the original type variables: a generics placeholder is replaced by its bound (`T extends Number` → `Number`) and type arguments are dropped (`List<T>` → `List`).
  `static Map<GenericsType.GenericsTypeName,GenericsType>`
  `extractPlaceholders(ClassNode type)`
  Returns the type parameter/argument relationships of the specified type.
  `static void`
  `extractPlaceholders(ClassNode type, Map<GenericsType.GenericsTypeName,GenericsType> placeholders)`
  Populates the supplied map with the type parameter/argument relationships of the specified type.
  `static void`
  `extractSuperClassGenerics(ClassNode type, ClassNode target, Map<String,ClassNode> spec)`
  `static ClassNode`
  `findActualTypeByGenericsPlaceholderName(String placeholderName, Map<GenericsType,GenericsType> genericsPlaceholderAndTypeMap)`
  Deprecated, for removal: This API element is subject to removal in a future version.
  `static ClassNode`
  `findParameterizedType(ClassNode genericsClass, ClassNode actualType)`
  Convenience method for `findParameterizedType(ClassNode,ClassNode,boolean)` with `tryToFindExactType` set to `false`.
  `static ClassNode`
  `findParameterizedType(ClassNode genericsClass, ClassNode actualType, boolean tryToFindExactType)`
  Gets the parameterized type by searching the whole class hierarchy according to generics class and actual receiver.
  `static ClassNode`
  `findParameterizedTypeFromCache(ClassNode genericsClass, ClassNode actualType)`
  Convenience method for `findParameterizedTypeFromCache(ClassNode,ClassNode,boolean)` with `tryToFindExactType` set to `false`.
  `static ClassNode`
  `findParameterizedTypeFromCache(ClassNode genericsClass, ClassNode actualType, boolean tryToFindExactType)`
  Try to get the parameterized type from the cache.
  `static ClassNode`
  `getSuperClass(ClassNode type, ClassNode target)`
  `static boolean`
  `hasNonPlaceHolders(ClassNode type)`
  Checks if the type has any non-placeholder (aka resolved) generics.
  `static boolean`
  `hasPlaceHolders(ClassNode type)`
  Checks if the type has any placeholder (aka unresolved) generics.
  `static boolean`
  `hasUnresolvedGenerics(ClassNode type)`
  Checks for any placeholder (aka unresolved) generics.
  `static Map<String,ClassNode>`
  `inferGenericsSpecFromOverrides(ClassNode impl, ClassNode superType, Map<String,ClassNode> oldSpec)`
  Recovers a `generics specification` for `superType` from `impl`'s instance methods.
  `static ClassNode`
  `makeClassSafe(Class klass)`
  `static ClassNode`
  `makeClassSafe0(ClassNode type, GenericsType... genericTypes)`
  `static ClassNode`
  `makeClassSafeWithGenerics(Class klass, ClassNode genericsType)`
  `static ClassNode`
  `makeClassSafeWithGenerics(ClassNode type, GenericsType... genericTypes)`
  `static Map<GenericsType,GenericsType>`
  `makeDeclaringAndActualGenericsTypeMap(ClassNode declaringClass, ClassNode actualReceiver)`
  Deprecated, for removal: This API element is subject to removal in a future version.
  `static Map<GenericsType,GenericsType>`
  `makeDeclaringAndActualGenericsTypeMapOfExactType(ClassNode declaringClass, ClassNode actualReceiver)`
  Deprecated, for removal: This API element is subject to removal in a future version.
  `static ClassNode`
  `newClass(ClassNode type)`
  `static ClassNode`
  `nonGeneric(ClassNode type)`
  `static ClassNode`
  `parameterizeInterfaceGenerics(ClassNode hint, ClassNode target)`
  Deprecated, for removal: This API element is subject to removal in a future version.
  Use #parameterizeType instead
  `static Tuple2<ClassNode[],ClassNode>`
  `parameterizeSAM(ClassNode samType)`
  Gets the parameter and return types of the abstract method of SAM.
  `static ClassNode`
  `parameterizeType(ClassNode hint, ClassNode target)`
  Interface class nodes retrieved from `ClassNode.getInterfaces()` or `ClassNode.getAllInterfaces()` are returned with generic type arguments.
  `static ClassNode[]`
  `parseClassNodesFromString(String option, SourceUnit sourceUnit, CompilationUnit compilationUnit, MethodNode mn, ASTNode usage)`
  `static String`
  `toGenericTypesString(GenericsType[] genericsTypes)`

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### EMPTY_GENERICS_ARRAY

    public static final GenericsType[] EMPTY_GENERICS_ARRAY
    An empty array of generic type arguments, used as a constant to avoid repeated allocations.
    Since:
      2.0.0

  - ### JAVA_LANG_OBJECT

    public static final String JAVA_LANG_OBJECT
    Canonical string representation of `java.lang.Object`.
    Since:
      3.0.0
    See Also:
      - Constant Field Values

- ## Constructor Details

  - ### GenericsUtils

    public GenericsUtils()

- ## Method Details

  - ### alignGenericTypes

    @Deprecated(forRemoval=true, since="2.3.0") public static GenericsType[] alignGenericTypes(GenericsType[] redirectGenericTypes, GenericsType[] parameterizedTypes, GenericsType[] alignmentTarget)
    Deprecated, for removal: This API element is subject to removal in a future version.
    You shouldn't call this method because it is inherently unreliable.
    Given a parameterized type and a generic type information, aligns actual type parameters. For example, if a class uses generic type

        <T,U,V>

    (redirectGenericTypes), is used with actual type parameters

        <java.lang.String, U,V>

    , then a class or interface using generic types

        <T,V>

    will be aligned to

        <java.lang.String,V>

    Parameters:
      `redirectGenericTypes` - the type arguments or the redirect class node
      `parameterizedTypes` - the actual type arguments used on this class node
      `alignmentTarget` - the generic type arguments to which we want to align to
    Returns:
      aligned type arguments
    Since:
      2.0.0

  - ### buildWildcardType

    public static GenericsType buildWildcardType(ClassNode... upperBounds)
    Generates a wildcard generic type in order to be used for checks against class nodes. See `GenericsType.isCompatibleWith(ClassNode)`.
    Since:
      2.0.0

  - ### extractPlaceholders

    public static Map<GenericsType.GenericsTypeName,GenericsType> extractPlaceholders(ClassNode type)
    Returns the type parameter/argument relationships of the specified type.
    Since:
      2.0.0

  - ### extractPlaceholders

    public static void extractPlaceholders(ClassNode type, Map<GenericsType.GenericsTypeName,GenericsType> placeholders)
    Populates the supplied map with the type parameter/argument relationships of the specified type.
    Since:
      2.0.0

  - ### toGenericTypesString

    public static String toGenericTypesString(GenericsType[] genericsTypes)
    Since:
      3.0.0

  - ### parameterizeInterfaceGenerics

    @Deprecated(forRemoval=true, since="2.5.0") public static ClassNode parameterizeInterfaceGenerics(ClassNode hint, ClassNode target)
    Deprecated, for removal: This API element is subject to removal in a future version.
    Use #parameterizeType instead
    Interface class nodes retrieved from `ClassNode.getInterfaces()` or `ClassNode.getAllInterfaces()` are returned with generic type arguments. This method allows returning a parameterized interface given the parameterized class node which implements this interface.
    Parameters:
      `hint` - the class node where generics types are parameterized
      `target` - the interface we want to parameterize generics types
    Returns:
      a parameterized interface class node
    Since:
      2.0.0

  - ### parameterizeType

    public static ClassNode parameterizeType(ClassNode hint, ClassNode target)
    Interface class nodes retrieved from `ClassNode.getInterfaces()` or `ClassNode.getAllInterfaces()` are returned with generic type arguments. This method allows returning a parameterized interface given the parameterized class node which implements this interface.
    Parameters:
      `hint` - the ClassNode where generics types are parameterized
      `target` - the interface we want to parameterize generics types
    Returns:
      a parameterized interface ClassNode
    Since:
      2.1.0

  - ### nonGeneric

    public static ClassNode nonGeneric(ClassNode type)
    Since:
      2.3.0

  - ### erasure

    public static ClassNode erasure(ClassNode type)
    Computes the erasure of a type, safe to declare in a generated signature that cannot carry the original type variables: a generics placeholder is replaced by its bound (`T extends Number` → `Number`) and type arguments are dropped (`List<T>` → `List`).
    Since:
      6.0.0

  - ### newClass

    public static ClassNode newClass(ClassNode type)
    Since:
      2.3.0

  - ### makeClassSafe

    public static ClassNode makeClassSafe(Class klass)
    Since:
      2.3.0

  - ### makeClassSafeWithGenerics

    public static ClassNode makeClassSafeWithGenerics(Class klass, ClassNode genericsType)
    Since:
      2.4.0

  - ### makeClassSafe0

    public static ClassNode makeClassSafe0(ClassNode type, GenericsType... genericTypes)
    Since:
      2.3.0

  - ### makeClassSafeWithGenerics

    public static ClassNode makeClassSafeWithGenerics(ClassNode type, GenericsType... genericTypes)
    Since:
      2.3.0

  - ### correctToGenericsSpec

    public static MethodNode correctToGenericsSpec(Map<String,ClassNode> genericsSpec, MethodNode mn)
    Since:
      2.3.0

  - ### correctToGenericsSpecRecurse

    public static ClassNode correctToGenericsSpecRecurse(Map<String,ClassNode> genericsSpec, ClassNode type)
    Since:
      2.3.0

  - ### correctToGenericsSpecRecurse

    public static ClassNode[] correctToGenericsSpecRecurse(Map<String,ClassNode> genericsSpec, ClassNode[] types)
    Since:
      2.4.1

  - ### correctToGenericsSpecRecurse

    public static ClassNode correctToGenericsSpecRecurse(Map<String,ClassNode> genericsSpec, ClassNode type, List<String> exclusions)
    Since:
      2.4.1

  - ### correctToGenericsSpec

    public static ClassNode correctToGenericsSpec(Map<String,ClassNode> genericsSpec, GenericsType type)
    Since:
      2.3.0

  - ### correctToGenericsSpec

    public static ClassNode correctToGenericsSpec(Map<String,ClassNode> genericsSpec, ClassNode type)
    Since:
      2.3.0

  - ### createGenericsSpec

    public static Map<String,ClassNode> createGenericsSpec(ClassNode type)
    Since:
      2.4.0

  - ### createGenericsSpec

    public static Map<String,ClassNode> createGenericsSpec(ClassNode type, Map<String,ClassNode> oldSpec)
    Since:
      2.3.0

  - ### applyGenericsSpec

    public static void applyGenericsSpec(ClassNode type, Map<String,ClassNode> genericsSpec)
    Writes `genericsSpec` onto `type` as an explicit type-argument list, filling any missing parameter from its bound (or `Object`). Mutates `type` in place; callers must pass a per-use copy such as an anonymous class's diamond super type, not a shared redirect.
    Since:
      6.0.0

  - ### inferGenericsSpecFromOverrides

    public static Map<String,ClassNode> inferGenericsSpecFromOverrides(ClassNode impl, ClassNode superType, Map<String,ClassNode> oldSpec)
    Recovers a `generics specification` for `superType` from `impl`'s instance methods. Used for diamond anonymous classes (GROOVY-12319 / JEP 213): type arguments of `Super<>` are not written in source, so they are read back from overrides such as `String process(String)` for `T process(T)`.

    The result uses the same `Map<String, ClassNode>` protocol as `createGenericsSpec(ClassNode, Map)` and `applyGenericsSpec(ClassNode, Map)`. Assignment / target typing remains the primary JLS 15.9.3 witness; this is the fallback used when the diamond is still empty.

    Since:
      6.0.0

  - ### diamondTargetOfAnonymousClass

    public static ClassNode diamondTargetOfAnonymousClass(ClassNode anonType)
    Diamond `<>` of an anonymous class is stored on its super type, or on an interface once `InnerClassVisitor` has moved an interface super type. Returns that node, or `null` if none still carries a diamond.
    Since:
      6.0.0

  - ### addMethodGenerics

    public static Map<String,ClassNode> addMethodGenerics(MethodNode node, Map<String,ClassNode> oldSpec)
    Since:
      2.4.1

  - ### extractSuperClassGenerics

    public static void extractSuperClassGenerics(ClassNode type, ClassNode target, Map<String,ClassNode> spec)
    Since:
      2.3.1

  - ### getSuperClass

    public static ClassNode getSuperClass(ClassNode type, ClassNode target)
    Since:
      3.0.0

  - ### parseClassNodesFromString

    public static ClassNode[] parseClassNodesFromString(String option, SourceUnit sourceUnit, CompilationUnit compilationUnit, MethodNode mn, ASTNode usage)
    Since:
      2.4.0

  - ### applyGenericsContextToPlaceHolders

    public static GenericsType[] applyGenericsContextToPlaceHolders(Map<String,ClassNode> genericsSpec, GenericsType[] oldPlaceHolders)
    Transforms generics types from an old context to a new context using the given spec. This method assumes all generics types will be placeholders. WARNING: The resulting generics types may or may not be placeholders after the transformation.
    Parameters:
      `genericsSpec` - the generics context information spec
      `oldPlaceHolders` - the old placeholders
    Returns:
      the new generics types
    Since:
      2.5.0

  - ### clearParameterizedTypeCache

    public static void clearParameterizedTypeCache()
    Clears the parameterized type cache.

    It is useful to IDE as the type being compiled are continuously being edited/altered; see GROOVY-8675

    Since:
      3.0.0

  - ### findParameterizedTypeFromCache

    public static ClassNode findParameterizedTypeFromCache(ClassNode genericsClass, ClassNode actualType)
    Convenience method for `findParameterizedTypeFromCache(ClassNode,ClassNode,boolean)` with `tryToFindExactType` set to `false`.
    Since:
      3.0.0

  - ### findParameterizedTypeFromCache

    public static ClassNode findParameterizedTypeFromCache(ClassNode genericsClass, ClassNode actualType, boolean tryToFindExactType)
    Try to get the parameterized type from the cache.

    If no cached item found, cache and return the result of `findParameterizedType(ClassNode,ClassNode,boolean)`.

    Since:
      3.0.0

  - ### findParameterizedType

    public static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode actualType)
    Convenience method for `findParameterizedType(ClassNode,ClassNode,boolean)` with `tryToFindExactType` set to `false`.
    Since:
      3.0.0

  - ### findParameterizedType

    public static ClassNode findParameterizedType(ClassNode genericsClass, ClassNode actualType, boolean tryToFindExactType)
    Gets the parameterized type by searching the whole class hierarchy according to generics class and actual receiver.

    `findParameterizedTypeFromCache(ClassNode,ClassNode,boolean)` is strongly recommended for better performance.

    Since:
      3.0.0

  - ### makeDeclaringAndActualGenericsTypeMap

    @Deprecated(forRemoval=true, since="5.0.0") public static Map<GenericsType,GenericsType> makeDeclaringAndActualGenericsTypeMap(ClassNode declaringClass, ClassNode actualReceiver)
    Deprecated, for removal: This API element is subject to removal in a future version.
    map declaring generics type to actual generics type, e.g. GROOVY-7204: declaring generics types: T, S extends Serializable actual generics types : String, Long the result map is [ T: String, S: Long ] The resolved types can not help us to choose methods correctly if the argument is a string: T: Object, S: Serializable so we need actual types: T: String, S: Long
    Since:
      3.0.0

  - ### makeDeclaringAndActualGenericsTypeMapOfExactType

    @Deprecated(forRemoval=true, since="5.0.0") public static Map<GenericsType,GenericsType> makeDeclaringAndActualGenericsTypeMapOfExactType(ClassNode declaringClass, ClassNode actualReceiver)
    Deprecated, for removal: This API element is subject to removal in a future version.
    The method is similar with `makeDeclaringAndActualGenericsTypeMap(ClassNode, ClassNode)`, The main difference is that the method will try to map all placeholders found to the relevant exact types, but the other will not try even if the parameterized type has placeholders
    Parameters:
      `declaringClass` - the generics class node declaring the generics types
      `actualReceiver` - the subclass class node
    Returns:
      the placeholder-to-actualtype mapping
    Since:
      3.0.0

  - ### hasNonPlaceHolders

    public static boolean hasNonPlaceHolders(ClassNode type)
    Checks if the type has any non-placeholder (aka resolved) generics.
    Since:
      3.0.0

  - ### hasPlaceHolders

    public static boolean hasPlaceHolders(ClassNode type)
    Checks if the type has any placeholder (aka unresolved) generics.
    Since:
      3.0.0

  - ### hasUnresolvedGenerics

    public static boolean hasUnresolvedGenerics(ClassNode type)
    Checks for any placeholder (aka unresolved) generics.
    Since:
      4.0.0

  - ### parameterizeSAM

    public static Tuple2<ClassNode[],ClassNode> parameterizeSAM(ClassNode samType)
    Gets the parameter and return types of the abstract method of SAM. If the abstract method is not parameterized, we will get generics placeholders, e.g. T, U For example, the abstract method of `Function` is

              R apply(T t);

    We parameterize the above interface as `Function<String, Integer>`, then the abstract method will be

              Integer apply(String t);

    When we call `parameterizeSAM` on the ClassNode `Function<String, Integer>`, we can get parameter types and return type of the above abstract method, i.e. ClassNode `ClassHelper.STRING_TYPE` and `ClassHelper.Integer_TYPE`
    Parameters:
      `samType` - the class node which contains only one abstract method
    Since:
      3.0.0

  - ### findActualTypeByGenericsPlaceholderName

    @Deprecated(forRemoval=true, since="5.0.0") public static ClassNode findActualTypeByGenericsPlaceholderName(String placeholderName, Map<GenericsType,GenericsType> genericsPlaceholderAndTypeMap)
    Deprecated, for removal: This API element is subject to removal in a future version.
    Gets the actual type according to the placeholder name.
    Parameters:
      `placeholderName` - the placeholder name (i.e. "T", "E", etc.)
      `genericsPlaceholderAndTypeMap` - the result of `makeDeclaringAndActualGenericsTypeMap(org.codehaus.groovy.ast.ClassNode, org.codehaus.groovy.ast.ClassNode)`
    Since:
      3.0.0