diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Types.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Types.java index c558f547e226f..18b163cb8bced 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Types.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Types.java @@ -19,6 +19,7 @@ import java.util.Set; import java.util.function.BiConsumer; import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.AnnotationTarget; import org.jboss.jandex.AnnotationValue; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; @@ -31,6 +32,7 @@ import org.jboss.jandex.Type.Kind; import org.jboss.jandex.TypeVariable; import org.jboss.jandex.WildcardType; +import org.jboss.logging.Logger; /** * @@ -38,6 +40,8 @@ */ final class Types { + static final Logger LOGGER = Logger.getLogger(Types.class); + private static final Type OBJECT_TYPE = Type.create(DotNames.OBJECT, Kind.CLASS); private Types() { @@ -148,9 +152,9 @@ static Set getProducerMethodTypeClosure(MethodInfo producerMethod, BeanDep "Producer method return type not found in index: " + producerMethod.returnType().name()); } if (Kind.CLASS.equals(returnType.kind())) { - types = getTypeClosure(returnTypeClassInfo, Collections.emptyMap(), beanDeployment, null); + types = getTypeClosure(returnTypeClassInfo, producerMethod, Collections.emptyMap(), beanDeployment, null); } else if (Kind.PARAMETERIZED_TYPE.equals(returnType.kind())) { - types = getTypeClosure(returnTypeClassInfo, + types = getTypeClosure(returnTypeClassInfo, producerMethod, buildResolvedMap(returnType.asParameterizedType().arguments(), returnTypeClassInfo.typeParameters(), Collections.emptyMap(), beanDeployment.getIndex()), beanDeployment, null); @@ -174,9 +178,9 @@ static Set getProducerFieldTypeClosure(FieldInfo producerField, BeanDeploy throw new IllegalArgumentException("Producer field type not found in index: " + producerField.type().name()); } if (Kind.CLASS.equals(fieldType.kind())) { - types = getTypeClosure(fieldClassInfo, Collections.emptyMap(), beanDeployment, null); + types = getTypeClosure(fieldClassInfo, producerField, Collections.emptyMap(), beanDeployment, null); } else if (Kind.PARAMETERIZED_TYPE.equals(fieldType.kind())) { - types = getTypeClosure(fieldClassInfo, + types = getTypeClosure(fieldClassInfo, producerField, buildResolvedMap(fieldType.asParameterizedType().arguments(), fieldClassInfo.typeParameters(), Collections.emptyMap(), beanDeployment.getIndex()), beanDeployment, null); @@ -199,7 +203,15 @@ static Set getClassBeanTypeClosure(ClassInfo classInfo, BeanDeployment bea return restrictBeanTypes(types, beanDeployment.getAnnotations(classInfo)); } - static Set getTypeClosure(ClassInfo classInfo, Map resolvedTypeParameters, + static Set getTypeClosure(ClassInfo classInfo, + Map resolvedTypeParameters, + BeanDeployment beanDeployment, BiConsumer> resolvedTypeVariablesConsumer) { + return getTypeClosure(classInfo, null, resolvedTypeParameters, beanDeployment, + resolvedTypeVariablesConsumer); + } + + static Set getTypeClosure(ClassInfo classInfo, AnnotationTarget producerFieldOrMethod, + Map resolvedTypeParameters, BeanDeployment beanDeployment, BiConsumer> resolvedTypeVariablesConsumer) { Set types = new HashSet<>(); List typeParameters = classInfo.typeParameters(); @@ -210,8 +222,19 @@ static Set getTypeClosure(ClassInfo classInfo, Map res } else { // Canonical ParameterizedType with unresolved type variables Type[] typeParams = new Type[typeParameters.size()]; + boolean skipThisType = false; for (int i = 0; i < typeParameters.size(); i++) { typeParams[i] = resolvedTypeParameters.get(typeParameters.get(i)); + // this should only be the case for producers; wildcard is not a legal bean type + // see https://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#legal_bean_types + if (typeParams[i].kind().equals(Kind.WILDCARD_TYPE) && producerFieldOrMethod != null) { + LOGGER.info("Producer " + + (producerFieldOrMethod.kind().equals(AnnotationTarget.Kind.FIELD) ? "field " : "method ") + + producerFieldOrMethod + + " contains a parameterized typed with a wildcard. This type is not a legal bean type" + + " according to CDI specification and will be ignored during bean resolution."); + skipThisType = true; + } } if (resolvedTypeVariablesConsumer != null) { Map resolved = new HashMap<>(); @@ -220,7 +243,9 @@ static Set getTypeClosure(ClassInfo classInfo, Map res } resolvedTypeVariablesConsumer.accept(classInfo, resolved); } - types.add(ParameterizedType.create(classInfo.name(), typeParams, null)); + if (!skipThisType) { + types.add(ParameterizedType.create(classInfo.name(), typeParams, null)); + } } // Interfaces for (Type interfaceType : classInfo.interfaceTypes()) { @@ -231,7 +256,8 @@ static Set getTypeClosure(ClassInfo classInfo, Map res resolved = buildResolvedMap(interfaceType.asParameterizedType().arguments(), interfaceClassInfo.typeParameters(), resolvedTypeParameters, beanDeployment.getIndex()); } - types.addAll(getTypeClosure(interfaceClassInfo, resolved, beanDeployment, resolvedTypeVariablesConsumer)); + types.addAll(getTypeClosure(interfaceClassInfo, producerFieldOrMethod, resolved, beanDeployment, + resolvedTypeVariablesConsumer)); } } // Superclass @@ -244,7 +270,8 @@ static Set getTypeClosure(ClassInfo classInfo, Map res superClassInfo.typeParameters(), resolvedTypeParameters, beanDeployment.getIndex()); } - types.addAll(getTypeClosure(superClassInfo, resolved, beanDeployment, resolvedTypeVariablesConsumer)); + types.addAll(getTypeClosure(superClassInfo, producerFieldOrMethod, resolved, beanDeployment, + resolvedTypeVariablesConsumer)); } } return types;