Skip to content

Commit

Permalink
CDI decorators - fix processing of decorated methods
Browse files Browse the repository at this point in the history
- resolves quarkusio#29230
  • Loading branch information
mkouba committed Nov 21, 2022
1 parent f914563 commit 61b9671
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -649,7 +649,7 @@ private void addDecoratedMethods(Map<MethodKey, DecorationInfo> decoratedMethods
}
}

List<DecoratorInfo> findMatchingDecorators(MethodInfo method, List<DecoratorInfo> decorators) {
private List<DecoratorInfo> findMatchingDecorators(MethodInfo method, List<DecoratorInfo> decorators) {
List<Type> methodParams = method.parameterTypes();
List<DecoratorInfo> matching = new ArrayList<>(decorators.size());
for (DecoratorInfo decorator : decorators) {
Expand All @@ -661,6 +661,10 @@ List<DecoratorInfo> findMatchingDecorators(MethodInfo method, List<DecoratorInfo
throw new DefinitionException(
"The class of the decorated type " + decoratedType + " was not found in the index");
}

Map<String, Type> resolvedTypeParameters = Types.resolveDecoratedTypeParams(decoratedTypeClass,
decorator);

for (MethodInfo decoratedMethod : decoratedTypeClass.methods()) {
if (!method.name().equals(decoratedMethod.name())) {
continue;
Expand All @@ -671,10 +675,12 @@ List<DecoratorInfo> findMatchingDecorators(MethodInfo method, List<DecoratorInfo
}
// Match the resolved parameter types
boolean matches = true;
decoratedMethodParams = Types.getResolvedParameters(decoratedTypeClass, method,
decoratedMethodParams = Types.getResolvedParameters(decoratedTypeClass, resolvedTypeParameters,
decoratedMethod,
beanDeployment.getBeanArchiveIndex());
for (int i = 0; i < methodParams.size(); i++) {
if (!methodParams.get(i).equals(decoratedMethodParams.get(i))) {
if (!beanDeployment.getDelegateInjectionPointResolver().matches(decoratedMethodParams.get(i),
methodParams.get(i))) {
matches = false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,24 +183,14 @@ private String generateDecoratorImplementation(String baseName, String targetPac
ClassInfo decoratedTypeClass = index
.getClassByName(decoratedType.name());
if (decoratedTypeClass == null) {
throw new IllegalStateException("TODO");
throw new IllegalStateException("Decorated type not found in the bean archive index: " + decoratedType);
}

// A decorated type can declare type parameters
// For example Converter<String> should result in a T -> String mapping
List<TypeVariable> typeParameters = decoratedTypeClass.typeParameters();
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).identifier(), typeArguments.get(i));
}
}
}
Map<String, org.jboss.jandex.Type> resolvedTypeParameters = Types.resolveDecoratedTypeParams(decoratedTypeClass,
decorator);

for (MethodInfo method : decoratedTypeClass.methods()) {
if (Methods.skipForDelegateSubclass(method)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,11 @@ private void processDecorator(DecoratorInfo decorator, BeanInfo bean, Type provi
paramHandles[paramIdx++] = subclassConstructor.getThis();
}
for (DecoratorInfo decoratorParameter : decoratorParameters) {
paramHandles[paramIdx++] = decoratorToResultHandle.get(decoratorParameter.getIdentifier());
ResultHandle decoratorHandle = decoratorToResultHandle.get(decoratorParameter.getIdentifier());
if (decoratorHandle == null) {
throw new IllegalStateException("Decorator handle must not be null");
}
paramHandles[paramIdx++] = decoratorHandle;
}
ResultHandle delegateSubclassInstance = subclassConstructor.newInstance(MethodDescriptor.ofConstructor(
delegateSubclass.getClassName(), constructorParameterTypes.toArray(new String[0])), paramHandles);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,23 @@ static Set<Type> getClassBeanTypeClosure(ClassInfo classInfo, BeanDeployment bea
return restrictBeanTypes(types, beanDeployment.getAnnotations(classInfo), beanDeployment.getBeanArchiveIndex());
}

static List<Type> getResolvedParameters(ClassInfo classInfo, MethodInfo method, IndexView index) {
return getResolvedParameters(classInfo, Collections.emptyMap(), method, index);
static Map<String, Type> resolveDecoratedTypeParams(ClassInfo decoratedTypeClass, DecoratorInfo decorator) {
// A decorated type can declare type parameters
// For example Converter<String> should result in a T -> String mapping
List<TypeVariable> typeParameters = decoratedTypeClass.typeParameters();
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).identifier(), typeArguments.get(i));
}
}
}
return resolvedTypeParameters;
}

static List<Type> getResolvedParameters(ClassInfo classInfo, Map<String, Type> resolvedMap,
Expand Down Expand Up @@ -588,7 +603,7 @@ static Type resolveTypeParam(Type typeParam, Map<String, Type> resolvedTypeParam
resolvedTypeParameters, index);
Type[] typeParams = new Type[typeParameters.size()];
for (int i = 0; i < typeParameters.size(); i++) {
typeParams[i] = resolveTypeParam(arguments.get(i), resolvedMap, index);
typeParams[i] = resolveTypeParam(typeParameters.get(i), resolvedMap, index);
}
return ParameterizedType.create(parameterizedType.name(), typeParams, null);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package io.quarkus.arc.test.decorators;

import static org.junit.jupiter.api.Assertions.assertEquals;

import javax.annotation.Priority;
import javax.decorator.Decorator;
import javax.decorator.Delegate;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.arc.Arc;
import io.quarkus.arc.test.ArcTestContainer;

public class SimpleDecoratorOverloadingTest {

@RegisterExtension
public ArcTestContainer container = new ArcTestContainer(Converter.class, SimpleConverter.class,
ConverterDecorator.class);

@Test
public void testDecoration() {
SimpleConverter converter = Arc.container().instance(SimpleConverter.class).get();
assertEquals("HOLA!", converter.convert(" holA!"));
assertEquals(42, converter.convert(42));
}

interface Converter {

int convert(int value);

String convert(String value);

}

@ApplicationScoped
static class SimpleConverter implements Converter {

@Override
public String convert(String value) {
return value.toUpperCase();
}

@Override
public int convert(int value) {
return -1 * value;
}

}

@Dependent
@Priority(1)
@Decorator
static class ConverterDecorator implements Converter {

@Inject
@Delegate
Converter delegate;

@Override
public String convert(String value) {
return delegate.convert(value.trim());
}

@Override
public int convert(int value) {
return -1 * delegate.convert(value);
}

}

}

0 comments on commit 61b9671

Please sign in to comment.