Skip to content

Commit

Permalink
ArC: fix decorators and interface default methods
Browse files Browse the repository at this point in the history
- fixes #35664

(cherry picked from commit ada6761)
  • Loading branch information
mkouba authored and gsmet committed Sep 4, 2023
1 parent d916ceb commit ff7bd6f
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ private static boolean skipForClientProxy(MethodInfo method, boolean transformUn
}

static boolean skipForDelegateSubclass(MethodInfo method) {
if (Modifier.isStatic(method.flags()) || method.isSynthetic() || isDefault(method)) {
if (Modifier.isStatic(method.flags()) || method.isSynthetic()) {
return true;
}
if (IGNORED_METHODS.contains(method.name())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -637,13 +637,10 @@ private void processDecorator(DecoratorInfo decorator, BeanInfo bean, Type provi
}

List<String> constructorParameterTypes = new ArrayList<>();
// Fields and constructor
FieldCreator subclassField = null;
if (decoratedMethods.size() != nextDecoratorsValues.size()) {
subclassField = delegateSubclass.getFieldCreator("subclass", subclass.getClassName())
.setModifiers(ACC_PRIVATE | ACC_FINAL);
constructorParameterTypes.add(subclass.getClassName());
}
// Holds a reference to the subclass of the decorated bean
FieldCreator subclassField = delegateSubclass.getFieldCreator("subclass", subclass.getClassName())
.setModifiers(ACC_PRIVATE | ACC_FINAL);
constructorParameterTypes.add(subclass.getClassName());
Map<DecoratorInfo, FieldDescriptor> nextDecoratorToField = new HashMap<>();
for (DecoratorInfo nextDecorator : decoratorParameters) {
FieldCreator nextDecoratorField = delegateSubclass
Expand All @@ -653,6 +650,7 @@ private void processDecorator(DecoratorInfo decorator, BeanInfo bean, Type provi
nextDecoratorToField.put(nextDecorator, nextDecoratorField.getFieldDescriptor());
}

// Constructor
MethodCreator constructor = delegateSubclass.getMethodCreator(Methods.INIT, "V",
constructorParameterTypes.toArray(new String[0]));
int param = 0;
Expand All @@ -664,10 +662,8 @@ private void processDecorator(DecoratorInfo decorator, BeanInfo bean, Type provi
constructor.getThis());
}
// Set fields
if (subclassField != null) {
constructor.writeInstanceField(
subclassField.getFieldDescriptor(), constructor.getThis(), constructor.getMethodParam(param++));
}
constructor.writeInstanceField(
subclassField.getFieldDescriptor(), constructor.getThis(), constructor.getMethodParam(param++));
for (FieldDescriptor field : nextDecoratorToField.values()) {
constructor.writeInstanceField(
field, constructor.getThis(), constructor.getMethodParam(param++));
Expand Down Expand Up @@ -700,10 +696,6 @@ private void processDecorator(DecoratorInfo decorator, BeanInfo bean, Type provi

for (MethodKey m : methods) {
MethodInfo method = m.method;
if (Methods.skipForDelegateSubclass(method)) {
continue;
}

MethodDescriptor methodDescriptor = MethodDescriptor.of(method);
MethodCreator forward = delegateSubclass.getMethodCreator(methodDescriptor);
// Exceptions
Expand Down Expand Up @@ -818,9 +810,7 @@ && isDecorated(decoratedMethodDescriptors, methodDescriptor, resolvedMethodDescr
// Create new delegate subclass instance and set the DecoratorDelegateProvider to satisfy the delegate IP
ResultHandle[] paramHandles = new ResultHandle[constructorParameterTypes.size()];
int paramIdx = 0;
if (subclassField != null) {
paramHandles[paramIdx++] = subclassConstructor.getThis();
}
paramHandles[paramIdx++] = subclassConstructor.getThis();
for (DecoratorInfo decoratorParameter : decoratorParameters) {
ResultHandle decoratorHandle = decoratorToResultHandle.get(decoratorParameter.getIdentifier());
if (decoratorHandle == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package io.quarkus.arc.test.decorators;

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

import jakarta.annotation.Priority;
import jakarta.decorator.Decorator;
import jakarta.decorator.Delegate;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.util.TypeLiteral;
import jakarta.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 DecoratorDefaultMethodTest {
@RegisterExtension
public ArcTestContainer container = new ArcTestContainer(Converter.class, ToLengthConverter.class,
NoopConverterDecorator.class);

@SuppressWarnings("serial")
@Test
public void testDecoration() {
Converter<String> converter = Arc.container().instance(new TypeLiteral<Converter<String>>() {
}).get();
assertEquals(5, converter.convert("Hola!"));
}

interface Converter<T> {
default int convert(T value) {
return Integer.MAX_VALUE;
}
}

@ApplicationScoped
static class ToLengthConverter implements Converter<String> {
@Override
public int convert(String value) {
return value.length();
}
}

@Priority(1)
@Decorator
static class NoopConverterDecorator implements Converter<String> {

@Inject
@Delegate
Converter<String> delegate;

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

}

0 comments on commit ff7bd6f

Please sign in to comment.