Skip to content

Commit

Permalink
Arc - log a warning when we detect wildcard as a bean type.
Browse files Browse the repository at this point in the history
  • Loading branch information
manovotn committed Oct 22, 2019
1 parent 994427c commit ca19197
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -31,13 +32,16 @@
import org.jboss.jandex.Type.Kind;
import org.jboss.jandex.TypeVariable;
import org.jboss.jandex.WildcardType;
import org.jboss.logging.Logger;

/**
*
* @author Martin Kouba
*/
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() {
Expand Down Expand Up @@ -148,9 +152,9 @@ static Set<Type> 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);
Expand All @@ -174,9 +178,9 @@ static Set<Type> 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);
Expand All @@ -191,15 +195,16 @@ static Set<Type> getClassBeanTypeClosure(ClassInfo classInfo, BeanDeployment bea
Set<Type> types;
List<TypeVariable> typeParameters = classInfo.typeParameters();
if (typeParameters.isEmpty()) {
types = getTypeClosure(classInfo, Collections.emptyMap(), beanDeployment, null);
types = getTypeClosure(classInfo, null, Collections.emptyMap(), beanDeployment, null);
} else {
types = getTypeClosure(classInfo, buildResolvedMap(typeParameters, typeParameters,
types = getTypeClosure(classInfo, null, buildResolvedMap(typeParameters, typeParameters,
Collections.emptyMap(), beanDeployment.getIndex()), beanDeployment, null);
}
return restrictBeanTypes(types, beanDeployment.getAnnotations(classInfo));
}

static Set<Type> getTypeClosure(ClassInfo classInfo, Map<TypeVariable, Type> resolvedTypeParameters,
static Set<Type> getTypeClosure(ClassInfo classInfo, AnnotationTarget producerFieldOrMethod,
Map<TypeVariable, Type> resolvedTypeParameters,
BeanDeployment beanDeployment, BiConsumer<ClassInfo, Map<TypeVariable, Type>> resolvedTypeVariablesConsumer) {
Set<Type> types = new HashSet<>();
List<TypeVariable> typeParameters = classInfo.typeParameters();
Expand All @@ -210,8 +215,19 @@ static Set<Type> getTypeClosure(ClassInfo classInfo, Map<TypeVariable, Type> 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<TypeVariable, Type> resolved = new HashMap<>();
Expand All @@ -220,7 +236,9 @@ static Set<Type> getTypeClosure(ClassInfo classInfo, Map<TypeVariable, Type> 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()) {
Expand All @@ -231,7 +249,8 @@ static Set<Type> getTypeClosure(ClassInfo classInfo, Map<TypeVariable, Type> 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
Expand All @@ -244,7 +263,8 @@ static Set<Type> getTypeClosure(ClassInfo classInfo, Map<TypeVariable, Type> res
superClassInfo.typeParameters(),
resolvedTypeParameters, beanDeployment.getIndex());
}
types.addAll(getTypeClosure(superClassInfo, resolved, beanDeployment, resolvedTypeVariablesConsumer));
types.addAll(getTypeClosure(superClassInfo, producerFieldOrMethod, resolved, beanDeployment,
resolvedTypeVariablesConsumer));
}
}
return types;
Expand All @@ -253,7 +273,7 @@ static Set<Type> getTypeClosure(ClassInfo classInfo, Map<TypeVariable, Type> res
static Map<ClassInfo, Map<TypeVariable, Type>> resolvedTypeVariables(ClassInfo classInfo,
BeanDeployment beanDeployment) {
Map<ClassInfo, Map<TypeVariable, Type>> resolvedTypeVariables = new HashMap<>();
getTypeClosure(classInfo, Collections.emptyMap(), beanDeployment, resolvedTypeVariables::put);
getTypeClosure(classInfo, null, Collections.emptyMap(), beanDeployment, resolvedTypeVariables::put);
return resolvedTypeVariables;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@
import static org.junit.jupiter.api.Assertions.assertTrue;

import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.FieldInfo;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.ParameterizedType;
import org.jboss.jandex.Type;
import org.jboss.jandex.Type.Kind;
Expand All @@ -21,14 +25,16 @@ public class TypesTest {

@Test
public void testGetTypeClosure() throws IOException {
IndexView index = Basics.index(Foo.class, Baz.class, Object.class);
IndexView index = Basics.index(Foo.class, Baz.class, Producer.class, Object.class, List.class, Collection.class,
Iterable.class);
DotName bazName = DotName.createSimple(Baz.class.getName());
DotName fooName = DotName.createSimple(Foo.class.getName());
DotName producerName = DotName.createSimple(Producer.class.getName());
ClassInfo fooClass = index.getClassByName(fooName);
Map<ClassInfo, Map<TypeVariable, Type>> resolvedTypeVariables = new HashMap<>();

// Baz, Foo<String>, Object
Set<Type> bazTypes = Types.getTypeClosure(index.getClassByName(bazName),
Set<Type> bazTypes = Types.getTypeClosure(index.getClassByName(bazName), null,
Collections.emptyMap(),
new BeanDeployment(index, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(),
Collections.emptyList(), null,
Expand Down Expand Up @@ -58,6 +64,23 @@ public void testGetTypeClosure() throws IOException {
assertEquals(DotNames.OBJECT, fooType.arguments().get(0).asTypeVariable().bounds().get(0).name());
}
}
ClassInfo producerClass = index.getClassByName(producerName);
String producersName = "produce";
MethodInfo producerMethod = producerClass.method(producersName);
// Object is the sole type
Set<Type> producerMethodTypes = Types.getProducerMethodTypeClosure(producerMethod,
new BeanDeployment(index, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(),
Collections.emptyList(), null,
false, Collections.emptyList(), Collections.emptyMap(), Collections.emptyList()));
assertEquals(1, producerMethodTypes.size());

// Object is the sole type
FieldInfo producerField = producerClass.field(producersName);
Set<Type> producerFieldTypes = Types.getProducerFieldTypeClosure(producerField,
new BeanDeployment(index, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(),
Collections.emptyList(), null,
false, Collections.emptyList(), Collections.emptyMap(), Collections.emptyList()));
assertEquals(1, producerFieldTypes.size());
}

static class Foo<T> {
Expand All @@ -69,4 +92,13 @@ static class Foo<T> {
static class Baz extends Foo<String> {

}

static class Producer {

public List<? extends Number> produce() {
return null;
}

List<? extends Number> produce;
}
}

0 comments on commit ca19197

Please sign in to comment.