Skip to content

Commit

Permalink
Fix type variable resolution in ArC's bean type closure search
Browse files Browse the repository at this point in the history
  • Loading branch information
Ladicek committed Sep 15, 2022
1 parent 92fba0a commit 7c77aa6
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import org.jboss.jandex.IndexView;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.Type;
import org.jboss.jandex.TypeVariable;

/**
*
Expand Down Expand Up @@ -120,7 +119,7 @@ Collection<Resource> generate(BeanInfo bean, String beanClassName,
if (!providerClass.typeParameters().isEmpty()) {
clientProxy.setSignature(AsmUtilCopy.getGeneratedSubClassSignature(providerClass, bean.getProviderType()));
}
Map<ClassInfo, Map<TypeVariable, Type>> resolvedTypeVariables = Types.resolvedTypeVariables(providerClass,
Map<ClassInfo, Map<String, Type>> resolvedTypeVariables = Types.resolvedTypeVariables(providerClass,
bean.getDeployment());
FieldCreator beanField = clientProxy.getFieldCreator(BEAN_FIELD, InjectableBean.class)
.setModifiers(ACC_PRIVATE | ACC_FINAL);
Expand Down Expand Up @@ -148,10 +147,10 @@ Collection<Resource> generate(BeanInfo bean, String beanClassName,
MethodDescriptor originalMethodDescriptor = MethodDescriptor.of(method);
MethodCreator forward = clientProxy.getMethodCreator(originalMethodDescriptor);
if (AsmUtilCopy.needsSignature(method)) {
Map<TypeVariable, Type> methodClassVariables = resolvedTypeVariables.get(method.declaringClass());
Map<String, Type> methodClassVariables = resolvedTypeVariables.get(method.declaringClass());
String signature = AsmUtilCopy.getSignature(method, typeVariable -> {
if (methodClassVariables != null) {
Type ret = methodClassVariables.get(typeVariable);
Type ret = methodClassVariables.get(typeVariable.identifier());
// let's not map a TV to itself
if (ret != typeVariable)
return ret;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,15 +187,15 @@ private String generateDecoratorImplementation(String baseName, String targetPac
// A decorated type can declare type parameters
// For example Converter<String> should result in a T -> String mapping
List<TypeVariable> typeParameters = decoratedTypeClass.typeParameters();
Map<TypeVariable, org.jboss.jandex.Type> resolvedTypeParameters = Collections.emptyMap();
Map<String, org.jboss.jandex.Type> resolvedTypeParameters = Collections.emptyMap();
if (!typeParameters.isEmpty()) {
resolvedTypeParameters = new HashMap<>();
// The delegate type can be used to infer the parameter types
org.jboss.jandex.Type type = decorator.getDelegateType();
if (type.kind() == Kind.PARAMETERIZED_TYPE) {
List<org.jboss.jandex.Type> typeArguments = type.asParameterizedType().arguments();
for (int i = 0; i < typeParameters.size(); i++) {
resolvedTypeParameters.put(typeParameters.get(i), typeArguments.get(i));
resolvedTypeParameters.put(typeParameters.get(i).identifier(), typeArguments.get(i));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.ParameterizedType;
import org.jboss.jandex.Type;
import org.jboss.jandex.TypeVariable;

/**
* Represents an injection point.
Expand Down Expand Up @@ -262,15 +261,15 @@ private static Type resolveType(Type type, ClassInfo beanClass, ClassInfo declar
if (type.kind() == org.jboss.jandex.Type.Kind.CLASS) {
return type;
}
Map<ClassInfo, Map<TypeVariable, Type>> resolvedTypeVariables = Types.resolvedTypeVariables(beanClass, beanDeployment);
Map<ClassInfo, Map<String, Type>> resolvedTypeVariables = Types.resolvedTypeVariables(beanClass, beanDeployment);
return resolveType(type, declaringClass, beanDeployment, resolvedTypeVariables);
}

private static Type resolveType(Type type, ClassInfo beanClass, BeanDeployment beanDeployment,
Map<ClassInfo, Map<TypeVariable, Type>> resolvedTypeVariables) {
Map<ClassInfo, Map<String, Type>> resolvedTypeVariables) {
if (type.kind() == org.jboss.jandex.Type.Kind.TYPE_VARIABLE) {
if (resolvedTypeVariables.containsKey(beanClass)) {
return resolvedTypeVariables.get(beanClass).getOrDefault(type.asTypeVariable(), type);
return resolvedTypeVariables.get(beanClass).getOrDefault(type.asTypeVariable().identifier(), type);
}
} else if (type.kind() == org.jboss.jandex.Type.Kind.PARAMETERIZED_TYPE) {
ParameterizedType parameterizedType = type.asParameterizedType();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.MethodParameterInfo;
import org.jboss.jandex.Type;
import org.jboss.jandex.TypeVariable;
import org.jboss.logging.Logger;

/**
Expand All @@ -54,7 +53,7 @@ static ObserverInfo create(BeanInfo declaringBean, MethodInfo observerMethod, In

Type observedType = observerMethod.parameterType(eventParameter.position());
if (Types.containsTypeVariable(observedType)) {
Map<TypeVariable, Type> resolvedTypeVariables = Types
Map<String, Type> resolvedTypeVariables = Types
.resolvedTypeVariables(declaringBean.getImplClazz(), declaringBean.getDeployment())
.getOrDefault(observerMethod.declaringClass(), Collections.emptyMap());
observedType = Types.resolveTypeParam(observedType, resolvedTypeVariables,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -480,15 +480,15 @@ private void processDecorator(DecoratorInfo decorator, BeanInfo bean, Type provi
// The delegate type can declare type parameters
// For example @Delegate Converter<String> should result in a T -> String mapping
List<TypeVariable> typeParameters = delegateTypeClass.typeParameters();
Map<TypeVariable, Type> resolvedTypeParameters = Collections.emptyMap();
Map<String, Type> resolvedTypeParameters = Collections.emptyMap();
if (!typeParameters.isEmpty()) {
resolvedTypeParameters = new HashMap<>();
// The delegate type can be used to infer the parameter types
Type delegateType = decorator.getDelegateType();
if (delegateType.kind() == Kind.PARAMETERIZED_TYPE) {
List<Type> typeArguments = delegateType.asParameterizedType().arguments();
for (int i = 0; i < typeParameters.size(); i++) {
resolvedTypeParameters.put(typeParameters.get(i), typeArguments.get(i));
resolvedTypeParameters.put(typeParameters.get(i).identifier(), typeArguments.get(i));
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ static List<Type> getResolvedParameters(ClassInfo classInfo, MethodInfo method,
return getResolvedParameters(classInfo, Collections.emptyMap(), method, index);
}

static List<Type> getResolvedParameters(ClassInfo classInfo, Map<TypeVariable, Type> resolvedMap,
static List<Type> getResolvedParameters(ClassInfo classInfo, Map<String, Type> resolvedMap,
MethodInfo method, IndexView index) {
List<TypeVariable> typeParameters = classInfo.typeParameters();
// E.g. Foo, T, List<String>
Expand Down Expand Up @@ -414,20 +414,21 @@ static List<Type> getResolvedParameters(ClassInfo classInfo, Map<TypeVariable, T
}

static Set<Type> getTypeClosure(ClassInfo classInfo, AnnotationTarget producerFieldOrMethod,
Map<TypeVariable, Type> resolvedTypeParameters,
BeanDeployment beanDeployment, BiConsumer<ClassInfo, Map<TypeVariable, Type>> resolvedTypeVariablesConsumer) {
Map<String, Type> resolvedTypeParameters,
BeanDeployment beanDeployment, BiConsumer<ClassInfo, Map<String, Type>> resolvedTypeVariablesConsumer) {
Set<Type> types = new HashSet<>();
List<TypeVariable> typeParameters = classInfo.typeParameters();

if (typeParameters.isEmpty() || !typeParameters.stream().allMatch(resolvedTypeParameters::containsKey)) {
if (typeParameters.isEmpty()
|| !typeParameters.stream().allMatch(it -> resolvedTypeParameters.containsKey(it.identifier()))) {
// Not a parameterized type or a raw type
types.add(Type.create(classInfo.name(), Kind.CLASS));
} 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));
typeParams[i] = resolvedTypeParameters.get(typeParameters.get(i).identifier());
// 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) {
Expand All @@ -440,9 +441,9 @@ static Set<Type> getTypeClosure(ClassInfo classInfo, AnnotationTarget producerFi
}
}
if (resolvedTypeVariablesConsumer != null) {
Map<TypeVariable, Type> resolved = new HashMap<>();
Map<String, Type> resolved = new HashMap<>();
for (int i = 0; i < typeParameters.size(); i++) {
resolved.put(typeParameters.get(i), typeParams[i]);
resolved.put(typeParameters.get(i).identifier(), typeParams[i]);
}
resolvedTypeVariablesConsumer.accept(classInfo, resolved);
}
Expand All @@ -457,7 +458,7 @@ static Set<Type> getTypeClosure(ClassInfo classInfo, AnnotationTarget producerFi
}
ClassInfo interfaceClassInfo = getClassByName(beanDeployment.getBeanArchiveIndex(), interfaceType.name());
if (interfaceClassInfo != null) {
Map<TypeVariable, Type> resolved = Collections.emptyMap();
Map<String, Type> resolved = Collections.emptyMap();
if (Kind.PARAMETERIZED_TYPE.equals(interfaceType.kind())) {
resolved = buildResolvedMap(interfaceType.asParameterizedType().arguments(),
interfaceClassInfo.typeParameters(), resolvedTypeParameters, beanDeployment.getBeanArchiveIndex());
Expand All @@ -470,7 +471,7 @@ static Set<Type> getTypeClosure(ClassInfo classInfo, AnnotationTarget producerFi
if (classInfo.superClassType() != null) {
ClassInfo superClassInfo = getClassByName(beanDeployment.getBeanArchiveIndex(), classInfo.superName());
if (superClassInfo != null) {
Map<TypeVariable, Type> resolved = Collections.emptyMap();
Map<String, Type> resolved = Collections.emptyMap();
if (Kind.PARAMETERIZED_TYPE.equals(classInfo.superClassType().kind())) {
resolved = buildResolvedMap(classInfo.superClassType().asParameterizedType().arguments(),
superClassInfo.typeParameters(),
Expand Down Expand Up @@ -509,9 +510,9 @@ static Set<Type> getDelegateTypeClosure(InjectionPointInfo delegateInjectionPoin
return types;
}

static Map<ClassInfo, Map<TypeVariable, Type>> resolvedTypeVariables(ClassInfo classInfo,
static Map<ClassInfo, Map<String, Type>> resolvedTypeVariables(ClassInfo classInfo,
BeanDeployment beanDeployment) {
Map<ClassInfo, Map<TypeVariable, Type>> resolvedTypeVariables = new HashMap<>();
Map<ClassInfo, Map<String, Type>> resolvedTypeVariables = new HashMap<>();
getTypeClosure(classInfo, null, Collections.emptyMap(), beanDeployment, resolvedTypeVariables::put);
return resolvedTypeVariables;
}
Expand Down Expand Up @@ -540,26 +541,27 @@ static Set<Type> restrictBeanTypes(Set<Type> types, Collection<AnnotationInstanc
return types;
}

static <T extends Type> Map<TypeVariable, Type> buildResolvedMap(List<T> resolvedArguments,
static <T extends Type> Map<String, Type> buildResolvedMap(List<T> resolvedArguments,
List<TypeVariable> typeVariables,
Map<TypeVariable, Type> resolvedTypeParameters, IndexView index) {
Map<TypeVariable, Type> resolvedMap = new HashMap<>();
Map<String, Type> resolvedTypeParameters, IndexView index) {
Map<String, Type> resolvedMap = new HashMap<>();
for (int i = 0; i < resolvedArguments.size(); i++) {
resolvedMap.put(typeVariables.get(i), resolveTypeParam(resolvedArguments.get(i), resolvedTypeParameters, index));
resolvedMap.put(typeVariables.get(i).identifier(),
resolveTypeParam(resolvedArguments.get(i), resolvedTypeParameters, index));
}
return resolvedMap;
}

static Type resolveTypeParam(Type typeParam, Map<TypeVariable, Type> resolvedTypeParameters, IndexView index) {
static Type resolveTypeParam(Type typeParam, Map<String, Type> resolvedTypeParameters, IndexView index) {
if (typeParam.kind() == Kind.TYPE_VARIABLE) {
return resolvedTypeParameters.getOrDefault(typeParam, typeParam);
return resolvedTypeParameters.getOrDefault(typeParam.asTypeVariable().identifier(), typeParam);
} else if (typeParam.kind() == Kind.PARAMETERIZED_TYPE) {
ParameterizedType parameterizedType = typeParam.asParameterizedType();
ClassInfo classInfo = getClassByName(index, parameterizedType.name());
if (classInfo != null) {
List<TypeVariable> typeParameters = classInfo.typeParameters();
List<Type> arguments = parameterizedType.arguments();
Map<TypeVariable, Type> resolvedMap = buildResolvedMap(arguments, typeParameters,
Map<String, Type> resolvedMap = buildResolvedMap(arguments, typeParameters,
resolvedTypeParameters, index);
Type[] typeParams = new Type[typeParameters.size()];
for (int i = 0; i < typeParameters.size(); i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import org.jboss.jandex.ParameterizedType;
import org.jboss.jandex.Type;
import org.jboss.jandex.Type.Kind;
import org.jboss.jandex.TypeVariable;
import org.junit.jupiter.api.Test;

public class TypesTest {
Expand All @@ -31,7 +30,7 @@ public void testGetTypeClosure() throws IOException {
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<>();
Map<ClassInfo, Map<String, Type>> resolvedTypeVariables = new HashMap<>();
BeanDeployment dummyDeployment = BeanProcessor.builder().setBeanArchiveIndex(index).build().getBeanDeployment();

// Baz, Foo<String>, Object
Expand All @@ -46,7 +45,7 @@ public void testGetTypeClosure() throws IOException {
null)));
assertEquals(resolvedTypeVariables.size(), 1);
assertTrue(resolvedTypeVariables.containsKey(fooClass));
assertEquals(resolvedTypeVariables.get(fooClass).get(fooClass.typeParameters().get(0)),
assertEquals(resolvedTypeVariables.get(fooClass).get(fooClass.typeParameters().get(0).identifier()),
Type.create(DotName.createSimple(String.class.getName()), Kind.CLASS));

resolvedTypeVariables.clear();
Expand Down

0 comments on commit 7c77aa6

Please sign in to comment.