diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java index 9beb087827f3b..0c32a3a479b9a 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java @@ -649,7 +649,7 @@ private void addDecoratedMethods(Map decoratedMethods } } - List findMatchingDecorators(MethodInfo method, List decorators) { + private List findMatchingDecorators(MethodInfo method, List decorators) { List methodParams = method.parameterTypes(); List matching = new ArrayList<>(decorators.size()); for (DecoratorInfo decorator : decorators) { @@ -661,6 +661,10 @@ List findMatchingDecorators(MethodInfo method, List resolvedTypeParameters = Types.resolveDecoratedTypeParams(decoratedTypeClass, + decorator); + for (MethodInfo decoratedMethod : decoratedTypeClass.methods()) { if (!method.name().equals(decoratedMethod.name())) { continue; @@ -671,10 +675,12 @@ List findMatchingDecorators(MethodInfo method, List should result in a T -> String mapping List typeParameters = decoratedTypeClass.typeParameters(); - Map 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 typeArguments = type.asParameterizedType().arguments(); - for (int i = 0; i < typeParameters.size(); i++) { - resolvedTypeParameters.put(typeParameters.get(i).identifier(), typeArguments.get(i)); - } - } - } + Map resolvedTypeParameters = Types.resolveDecoratedTypeParams(decoratedTypeClass, + decorator); for (MethodInfo method : decoratedTypeClass.methods()) { if (Methods.skipForDelegateSubclass(method)) { diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/SubclassGenerator.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/SubclassGenerator.java index e8fc595c680cd..4f3da34dd5eff 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/SubclassGenerator.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/SubclassGenerator.java @@ -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); 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 663b3ee491792..0b914cad9ef5b 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 @@ -384,8 +384,23 @@ static Set getClassBeanTypeClosure(ClassInfo classInfo, BeanDeployment bea return restrictBeanTypes(types, beanDeployment.getAnnotations(classInfo), beanDeployment.getBeanArchiveIndex()); } - static List getResolvedParameters(ClassInfo classInfo, MethodInfo method, IndexView index) { - return getResolvedParameters(classInfo, Collections.emptyMap(), method, index); + static Map resolveDecoratedTypeParams(ClassInfo decoratedTypeClass, DecoratorInfo decorator) { + // A decorated type can declare type parameters + // For example Converter should result in a T -> String mapping + List typeParameters = decoratedTypeClass.typeParameters(); + Map 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 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 getResolvedParameters(ClassInfo classInfo, Map resolvedMap, @@ -588,7 +603,7 @@ static Type resolveTypeParam(Type typeParam, Map 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); } diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/SimpleDecoratorOverloadingTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/SimpleDecoratorOverloadingTest.java new file mode 100644 index 0000000000000..cd66ec68ebebf --- /dev/null +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/SimpleDecoratorOverloadingTest.java @@ -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); + } + + } + +}