Repository: micronaut-projects/micronaut-core
File: inject/src/main/java/io/micronaut/inject/qualifiers/MatchArgumentQualifier.java (Java)

Code before:
 *
 * @param <T> The type
 * @author Denis Stepanov
 * @since 4.6
 */
@Internal
public final class MatchArgumentQualifier<T> implements Qualifier<T> {

    private static final Logger LOG = ClassUtils.getLogger(MatchArgumentQualifier.class);
    private final Argument<?> argument;
    private final Argument<?> superArgument;

    private MatchArgumentQualifier(Argument<?> argument, Argument<?> superArgument) {
        this.argument = argument;
        this.superArgument = superArgument;
    }

    public static <T> MatchArgumentQualifier<T> ofArgument(Argument<?> argument) {
        return new MatchArgumentQualifier<>(
            argument,
            null
        );
    }

    /**
     * Finds matches of a type with a generic of a higher kind types (types that extend the type or are equal to it).
     * The generic argument is assignable from the candidate generic type.
     * Use-cases are generic deserializers, readers.
     * Java example:
     * MyReader[ArrayList[String]] candidate = ...;
     * MyReader[? extends List[String]] aMatch = candidate;
     *
     * @param beanType        The type of the beans
     * @param genericArgument The generic argument of the bean type
     * @param <T>             The bean type
     * @return The qualifier
     */
    public static <T> MatchArgumentQualifier<T> ofHigherTypes(Class<T> beanType, Argument<?> genericArgument) {
        Argument<?> superArgument = Argument.ofTypeVariable(genericArgument.getType(), null, genericArgument.getAnnotationMetadata(), genericArgument.getTypeParameters());
        return new MatchArgumentQualifier<>(
            Argument.of(beanType, superArgument),
            superArgument
        );
    }

    /**
     * Finds matches of a type with a generic of a lower kind types (types that is a super type or are equal to it).
     * The candidate generic type is assignable from the generic argument.
     * Use-cases are generic serializers, writers.
     * Java example:
     * MyWriter[String]  candidate = ...;

Review comment (suggestion):
"higher-kinded types" are something else, java doesn't have them. please rename this

Code after:
 * A {@link Qualifier} that filters beans according to the type arguments.
 *
 * @param <T> The type
 * @author Denis Stepanov
 * @since 4.6
 */
@Internal
public final class MatchArgumentQualifier<T> implements Qualifier<T> {

    private static final Logger LOG = ClassUtils.getLogger(MatchArgumentQualifier.class);
    private final Argument<?> argument;
    private final Argument<?> covariantArgument;

    private MatchArgumentQualifier(Argument<?> argument, Argument<?> covariantArgument) {
        this.argument = argument;
        this.covariantArgument = covariantArgument;
    }

    public static <T> MatchArgumentQualifier<T> ofArgument(Argument<?> argument) {
        return new MatchArgumentQualifier<>(
            argument,
            null
        );
    }

    /**
     * Finds matches of a type with a covariant generic type (types that extend the type or are equal to it).
     * The generic argument is assignable from the candidate generic type.
     * Use-cases are generic deserializers, readers.
     *
     * <pre>
     * Java example:
     * {@code MyReader<ArrayList<String>> candidate = ...; }
     * {@code MyReader<? extends List<String>> aMatch = candidate; }
     * </pre>
     *
     * @param beanType        The type of the beans
     * @param genericArgument The generic argument of the bean type
     * @param <T>             The bean type
     * @return The qualifier
     */
    @NonNull
    public static <T> MatchArgumentQualifier<T> covariant(@NonNull Class<T> beanType, @NonNull Argument<?> genericArgument) {
        Argument<?> covariantArgument = Argument.ofTypeVariable(genericArgument.getType(), null, genericArgument.getAnnotationMetadata(), genericArgument.getTypeParameters());
        return new MatchArgumentQualifier<>(
            Argument.of(beanType, covariantArgument),
            covariantArgument
        );
    }

    /**