From acf9283069f2588b22ef21351527ed355285cf29 Mon Sep 17 00:00:00 2001 From: Matej Novotny Date: Wed, 22 May 2024 16:00:53 +0200 Subject: [PATCH 1/3] Arc - improve injection point transformation API --- .../processor/AnnotationsTransformation.java | 20 +++++-- .../AnnotationsTransformationContext.java | 26 ++++++++- .../arc/processor/InjectionPointInfo.java | 57 ++++++++++++++----- .../arc/processor/InjectionPointModifier.java | 15 +++-- .../processor/InjectionPointsTransformer.java | 40 ++++++++++++- .../quarkus/arc/processor/ObserverInfo.java | 2 +- .../arc/processor/ObserverTransformer.java | 4 +- 7 files changed, 132 insertions(+), 32 deletions(-) diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/AnnotationsTransformation.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/AnnotationsTransformation.java index 43c58c0593824..fbeb0653bfe7b 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/AnnotationsTransformation.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/AnnotationsTransformation.java @@ -36,9 +36,13 @@ public interface AnnotationsTransformation + * If you need to add an annotation instance to a method parameter and the annotation target is the whole method, use + * methods consuming {@link AnnotationInstance} directly and supply the correct {@link MethodParameterInfo}. * * @param annotationType * @param values @@ -47,9 +51,13 @@ public interface AnnotationsTransformation annotationType, AnnotationValue... values); /** - * NOTE: The annotation target is derived from the transformation context.. If you need to add an annotation instance - * to a method parameter use methods consuming {@link AnnotationInstance} directly and supply the correct - * {@link MethodParameterInfo}. + * NOTE: The annotation will belong to an annotation target which is derived from the transformation context. + * Each transformation context has means to obtain its annotation target such as + * {@link AnnotationsTransformer.TransformationContext#getTarget()} or + * {@link InjectionPointsTransformer.TransformationContext#getAnnotationTarget()}. + *

+ * If you need to add an annotation instance to a method parameter and the annotation target is the whole method, use + * methods consuming {@link AnnotationInstance} directly and supply the correct {@link MethodParameterInfo}. * * @param name * @param values diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/AnnotationsTransformationContext.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/AnnotationsTransformationContext.java index 5a46fac8355de..1faa971a8a52a 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/AnnotationsTransformationContext.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/AnnotationsTransformationContext.java @@ -18,6 +18,7 @@ abstract class AnnotationsTransformationContext getAllAnnotations() { + return getAllAnnotationForTarget(getTarget()); + } + + public Collection getAllTargetAnnotations() { + return getAllAnnotationForTarget(getAnnotationTarget()); + } + + private Collection getAllAnnotationForTarget(AnnotationTarget target) { AnnotationStore annotationStore = get(BuildExtension.Key.ANNOTATION_STORE); if (annotationStore == null) { throw new IllegalStateException( "Attempted to use the getAllAnnotations() method but AnnotationStore wasn't initialized."); } - return annotationStore.getAnnotations(getTarget()); + // Jandex overlay in compatible mode won't allow us to query for METHOD_PARAMETER + // hence if the "target" is method param, we query whole method and filter it + if (AnnotationTarget.Kind.METHOD_PARAMETER.equals(target.kind())) { + return Annotations.getParameterAnnotations(at -> annotationStore.getAnnotations(at), + target.asMethodParameter().method(), target.asMethodParameter().position()); + } else { + return annotationStore.getAnnotations(target); + } } } diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/InjectionPointInfo.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/InjectionPointInfo.java index a14c86d306d03..3156f6a63009e 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/InjectionPointInfo.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/InjectionPointInfo.java @@ -61,7 +61,7 @@ static InjectionPointInfo fromField(FieldInfo field, ClassInfo beanClass, BeanDe } Type type = resolveType(field.type(), beanClass, field.declaringClass(), beanDeployment); return new InjectionPointInfo(type, - transformer.applyTransformers(type, field, qualifiers), field, -1, + transformer.applyTransformers(type, field, qualifiers), field, null, contains(annotations, DotNames.TRANSIENT_REFERENCE), contains(annotations, DotNames.DELEGATE)); } @@ -70,7 +70,7 @@ static InjectionPointInfo fromResourceField(FieldInfo field, ClassInfo beanClass Type type = resolveType(field.type(), beanClass, field.declaringClass(), beanDeployment); return new InjectionPointInfo(type, transformer.applyTransformers(type, field, new HashSet<>(Annotations.onlyRuntimeVisible(field.annotations()))), - InjectionPointKind.RESOURCE, field, -1, false, false); + InjectionPointKind.RESOURCE, field, null, false, false); } static List fromMethod(MethodInfo method, ClassInfo beanClass, BeanDeployment beanDeployment, @@ -100,15 +100,15 @@ static List fromMethod(MethodInfo method, ClassInfo beanClas } Type type = resolveType(paramType, beanClass, method.declaringClass(), beanDeployment); injectionPoints.add(new InjectionPointInfo(type, - transformer.applyTransformers(type, method, position, paramQualifiers), - method, position, contains(paramAnnotations, DotNames.TRANSIENT_REFERENCE), + transformer.applyTransformers(type, method, method.parameters().get(position), paramQualifiers), + method, method.parameters().get(position), contains(paramAnnotations, DotNames.TRANSIENT_REFERENCE), contains(paramAnnotations, DotNames.DELEGATE))); } return injectionPoints; } static InjectionPointInfo fromSyntheticInjectionPoint(TypeAndQualifiers typeAndQualifiers) { - return new InjectionPointInfo(typeAndQualifiers, InjectionPointKind.CDI, null, -1, false, false); + return new InjectionPointInfo(typeAndQualifiers, InjectionPointKind.CDI, null, null, false, false); } private final TypeAndQualifiers typeAndQualifiers; @@ -117,25 +117,30 @@ static InjectionPointInfo fromSyntheticInjectionPoint(TypeAndQualifiers typeAndQ private final InjectionPointKind kind; private final boolean hasDefaultQualifier; private final AnnotationTarget target; + // once we remove #getTarget(), 'target' field should contain method parameter AnnotationTarget for method parameter injection + // can be null for field injection as well as synth injection point + private final AnnotationTarget methodParameterTarget; private final int position; private final boolean isTransientReference; private final boolean isDelegate; - InjectionPointInfo(Type requiredType, Set requiredQualifiers, AnnotationTarget target, int position, + InjectionPointInfo(Type requiredType, Set requiredQualifiers, AnnotationTarget target, + AnnotationTarget methodParameterTarget, boolean isTransientReference, boolean isDelegate) { - this(requiredType, requiredQualifiers, InjectionPointKind.CDI, target, position, isTransientReference, isDelegate); + this(requiredType, requiredQualifiers, InjectionPointKind.CDI, target, methodParameterTarget, isTransientReference, + isDelegate); } InjectionPointInfo(Type requiredType, Set requiredQualifiers, InjectionPointKind kind, - AnnotationTarget target, int position, boolean isTransientReference, boolean isDelegate) { + AnnotationTarget target, AnnotationTarget methodParameterTarget, boolean isTransientReference, boolean isDelegate) { this(new TypeAndQualifiers(requiredType, requiredQualifiers.isEmpty() ? Collections.singleton(AnnotationInstance.create(DotNames.DEFAULT, null, Collections.emptyList())) : requiredQualifiers), - kind, target, position, isTransientReference, isDelegate); + kind, target, methodParameterTarget, isTransientReference, isDelegate); } InjectionPointInfo(TypeAndQualifiers typeAndQualifiers, InjectionPointKind kind, - AnnotationTarget target, int position, boolean isTransientReference, boolean isDelegate) { + AnnotationTarget target, AnnotationTarget methodParameterTarget, boolean isTransientReference, boolean isDelegate) { this.typeAndQualifiers = typeAndQualifiers; this.resolvedBean = new AtomicReference(null); this.targetBean = new AtomicReference(null); @@ -143,7 +148,9 @@ static InjectionPointInfo fromSyntheticInjectionPoint(TypeAndQualifiers typeAndQ this.hasDefaultQualifier = typeAndQualifiers.qualifiers.size() == 1 && typeAndQualifiers.qualifiers.iterator().next().name().equals(DotNames.DEFAULT); this.target = target; - this.position = position; + this.methodParameterTarget = methodParameterTarget; + this.position = (methodParameterTarget == null || !Kind.METHOD_PARAMETER.equals(methodParameterTarget.kind())) ? -1 + : methodParameterTarget.asMethodParameter().position(); this.isTransientReference = isTransientReference; this.isDelegate = isDelegate; @@ -229,20 +236,35 @@ TypeAndQualifiers getTypeAndQualifiers() { } /** + * This method is deprecated and will be removed at some point after Quarkus 3.15. + * Use {@link #getAnnotationTarget()} instead. + * Both methods behave equally except for method parameter injection points where {@code getAnnotationTarget()} + * returns method parameter as {@link AnnotationTarget} instead of the whole method. + *

* For injected params, this method returns the corresponding method and not the param itself. * * @return the annotation target or {@code null} in case of synthetic injection point */ + @Deprecated(forRemoval = true, since = "3.12") public AnnotationTarget getTarget() { return target; } + /** + * Unlike {@link #getTarget()}, for injected params, this method returns the method parameter itself. + * + * @return the annotation target or {@code null} in case of synthetic injection point + */ + public AnnotationTarget getAnnotationTarget() { + return methodParameterTarget == null ? target : methodParameterTarget; + } + public boolean isField() { return target != null && target.kind() == Kind.FIELD; } public boolean isParam() { - return target != null && target.kind() == Kind.METHOD; + return methodParameterTarget != null && methodParameterTarget.kind() == Kind.METHOD_PARAMETER; } public boolean isTransient() { @@ -272,7 +294,7 @@ public boolean hasResolvedBean() { } /** - * @return the parameter position or {@code -1} for a field injection point + * @return the parameter position or {@code -1} for a field injection point or synthetic injection point */ public int getPosition() { return position; @@ -297,6 +319,15 @@ public String getTargetInfo() { method = "#" + method + "()"; } return "parameter '" + param + "' of " + target.asMethod().declaringClass().name() + method; + case METHOD_PARAMETER: + String name = methodParameterTarget.asMethodParameter().method().name(); + if (name.equals(Methods.INIT)) { + name = " constructor"; + } else { + name = "#" + name + "()"; + } + return "parameter '" + methodParameterTarget.asMethodParameter().name() + "' of " + + methodParameterTarget.asMethodParameter().method().declaringClass().name() + name; default: return target.toString(); } diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/InjectionPointModifier.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/InjectionPointModifier.java index 53dedded292d0..bcac6d1bf086d 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/InjectionPointModifier.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/InjectionPointModifier.java @@ -29,28 +29,30 @@ public class InjectionPointModifier { this.transformers = transformers; } - public Set applyTransformers(Type type, AnnotationTarget target, Integer paramPosition, + public Set applyTransformers(Type type, AnnotationTarget target, AnnotationTarget methodParameterTarget, Set qualifiers) { // with no transformers, we just immediately return original set of qualifiers if (transformers.isEmpty()) { return qualifiers; } - TransformationContextImpl transformationContext = new TransformationContextImpl(buildContext, target, qualifiers); + TransformationContextImpl transformationContext = new TransformationContextImpl(buildContext, target, + methodParameterTarget, qualifiers); for (InjectionPointsTransformer transformer : transformers) { if (transformer.appliesTo(type)) { transformer.transform(transformationContext); } } - if (paramPosition != null && AnnotationTarget.Kind.METHOD.equals(target.kind())) { + if (methodParameterTarget != null && AnnotationTarget.Kind.METHOD_PARAMETER.equals(methodParameterTarget.kind())) { // only return set of qualifiers related to the given method parameter return transformationContext.getQualifiers().stream().filter( - annotationInstance -> target.asMethod().parameters().get(paramPosition).equals(annotationInstance.target())) + annotationInstance -> methodParameterTarget.equals(annotationInstance.target())) .collect(Collectors.toSet()); } else { return transformationContext.getQualifiers(); } } + // method variant used for field and resource field injection; a case where we don't need to deal with method. params public Set applyTransformers(Type type, AnnotationTarget target, Set qualifiers) { return applyTransformers(type, target, null, qualifiers); } @@ -59,13 +61,14 @@ static class TransformationContextImpl extends AnnotationsTransformationContext< implements InjectionPointsTransformer.TransformationContext { public TransformationContextImpl(BuildContext buildContext, AnnotationTarget target, + AnnotationTarget methodParameterTarget, Set annotations) { - super(buildContext, target, annotations); + super(buildContext, target, methodParameterTarget, annotations); } @Override public InjectionPointsTransformer.Transformation transform() { - return new InjectionPointsTransformer.Transformation(new HashSet<>(getAnnotations()), getTarget(), + return new InjectionPointsTransformer.Transformation(new HashSet<>(getAnnotations()), getAnnotationTarget(), this::setAnnotations); } diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/InjectionPointsTransformer.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/InjectionPointsTransformer.java index cb0fcde50feb9..783d160525885 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/InjectionPointsTransformer.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/InjectionPointsTransformer.java @@ -35,12 +35,25 @@ public interface InjectionPointsTransformer extends BuildExtension { interface TransformationContext extends BuildExtension.BuildContext { /** + * This method is deprecated and will be removed at some point after Quarkus 3.15. + * Use {@link #getAnnotationTarget()} instead. + *

* Returns {@link AnnotationTarget} representing this injection point. + * For injected parameters, this method returns the {@link AnnotationTarget} of the whole method. * * @return the annotation target of this injection point */ + @Deprecated(forRemoval = true, since = "3.12") AnnotationTarget getTarget(); + /** + * Returns {@link AnnotationTarget} representing this injection point. + * Unlike {@link #getTarget()}, for injected parameters, this method returns the method parameter. + * + * @return the annotation target of this injection point + */ + AnnotationTarget getAnnotationTarget(); + /** * Returns current set of annotations instances - qualifiers. * @@ -49,9 +62,15 @@ interface TransformationContext extends BuildExtension.BuildContext { Set getQualifiers(); /** - * Retrieves all annotations attached to the {@link AnnotationTarget} that this transformer operates on - * even if they were altered by {@code AnnotationsTransformer}. This method is preferred to manual inspection - * of {@link AnnotationTarget} which may, in some corner cases, hold outdated information. + * This method is deprecated and will be removed at some point after Quarkus 3.15. + * Use {@link #getAllTargetAnnotations()} instead. + *

+ * Retrieves all annotations attached to the {@link AnnotationTarget} that this transformer operates on. + * This {@link AnnotationTarget} is equal to what the {@link #getTarget()} ()} method returns. + * + * The result includes annotations that were altered by {@code AnnotationsTransformer}. + * This method is preferred to manual inspection of {@link AnnotationTarget} which may, in some corner cases, + * hold outdated information. * * The resulting set of annotations contains all annotations, not just CDI qualifiers. * If the annotation target is a method, then this set contains annotations that belong to the method itself @@ -59,8 +78,23 @@ interface TransformationContext extends BuildExtension.BuildContext { * * @return collection of all annotations related to given {@link AnnotationTarget} */ + @Deprecated(forRemoval = true, since = "3.12") Collection getAllAnnotations(); + /** + * Retrieves all annotations attached to the {@link AnnotationTarget} that this transformer operates on. + * This {@link AnnotationTarget} is equal to what the {@link #getAnnotationTarget()} method returns. + * + * The result includes annotations that were altered by {@code AnnotationsTransformer}. + * This method is preferred to manual inspection of {@link AnnotationTarget} which may, in some corner cases, + * hold outdated information. + * + * The resulting set of annotations contains all annotations, not just CDI qualifiers. + * + * @return collection of all annotations related to given {@link AnnotationTarget} + */ + Collection getAllTargetAnnotations(); + /** * The transformation is not applied until the {@link Transformation#done()} method is invoked. * diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ObserverInfo.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ObserverInfo.java index 1c75166c852ed..85d84eee33b0c 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ObserverInfo.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ObserverInfo.java @@ -400,7 +400,7 @@ private static class ObserverTransformationContext extends AnnotationsTransforma public ObserverTransformationContext(BuildContext buildContext, AnnotationTarget target, Type observedType, Set qualifiers, Reception reception, TransactionPhase transactionPhase, Integer priority, boolean async) { - super(buildContext, target, qualifiers); + super(buildContext, target, null, qualifiers); this.observedType = observedType; this.reception = reception; this.transactionPhase = transactionPhase; diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ObserverTransformer.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ObserverTransformer.java index 3d7883c42ae3b..d463575bb8640 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ObserverTransformer.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ObserverTransformer.java @@ -78,7 +78,7 @@ interface TransformationContext extends BuildExtension.BuildContext { * Retrieves all annotations declared on the observer method. This method is preferred to manual inspection * of {@link #getMethod()} which may, in some corner cases, hold outdated information. *

- * The resulting set of annotations contains contains annotations that belong to the method itself + * The resulting set of annotations contains annotations that belong to the method itself * as well as to its parameters. * * @return collection of all annotations or an empty list in case of synthetic observer @@ -119,7 +119,7 @@ interface ObserverTransformation extends AnnotationsTransformation Date: Thu, 23 May 2024 17:41:41 +0200 Subject: [PATCH 2/3] Replace usages of now deprecated APIs --- .../arc/deployment/ConfigBuildStep.java | 33 ++++---- .../grpc/deployment/GrpcClientProcessor.java | 12 +-- .../qute/deployment/QuteProcessor.java | 6 +- .../QuarkusSecurityJpaProcessor.java | 4 +- .../SmallRyeContextPropagationProcessor.java | 84 +++++++------------ .../cdi/ConfiguredAndSharedBeansTest.java | 11 ++- .../deployment/WiringHelper.java | 5 +- .../quarkus/arc/processor/BeanGenerator.java | 12 +-- .../io/quarkus/arc/processor/BuiltinBean.java | 8 +- .../io/quarkus/arc/processor/Injection.java | 14 ++-- .../java/io/quarkus/arc/processor/Types.java | 4 +- .../bcextensions/InjectionPointInfoImpl.java | 9 +- .../InjectionPointTransformerTest.java | 34 +++++--- .../BeanDeploymentValidatorTest.java | 4 +- .../resource/ResourceInjectionTest.java | 2 +- 15 files changed, 114 insertions(+), 128 deletions(-) diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigBuildStep.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigBuildStep.java index e553cca9386e5..2e4343ed1d1da 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigBuildStep.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/ConfigBuildStep.java @@ -14,7 +14,7 @@ import static org.jboss.jandex.AnnotationInstance.create; import static org.jboss.jandex.AnnotationTarget.Kind.CLASS; import static org.jboss.jandex.AnnotationTarget.Kind.FIELD; -import static org.jboss.jandex.AnnotationTarget.Kind.METHOD; +import static org.jboss.jandex.AnnotationTarget.Kind.METHOD_PARAMETER; import static org.jboss.jandex.AnnotationValue.createStringValue; import java.util.ArrayList; @@ -42,6 +42,7 @@ import org.jboss.jandex.DotName; import org.jboss.jandex.FieldInfo; import org.jboss.jandex.MethodInfo; +import org.jboss.jandex.MethodParameterInfo; import org.jboss.jandex.Type; import org.jboss.jandex.Type.Kind; @@ -174,12 +175,12 @@ void configPropertyInjectionPoints( } else { // org.acme.Foo.config if (injectionPoint.isField()) { - FieldInfo field = injectionPoint.getTarget().asField(); + FieldInfo field = injectionPoint.getAnnotationTarget().asField(); propertyName = getPropertyName(field.name(), field.declaringClass()); } else if (injectionPoint.isParam()) { - MethodInfo method = injectionPoint.getTarget().asMethod(); - propertyName = getPropertyName(method.parameterName(injectionPoint.getPosition()), - method.declaringClass()); + MethodParameterInfo methodParameterInfo = injectionPoint.getAnnotationTarget().asMethodParameter(); + propertyName = getPropertyName(methodParameterInfo.name(), + methodParameterInfo.method().declaringClass()); } else { throw new IllegalStateException("Unsupported injection point target: " + injectionPoint); } @@ -205,8 +206,8 @@ void configPropertyInjectionPoints( propertyDefaultValue = defaultValue.asString(); } - if (injectionPoint.getTarget().kind().equals(METHOD) - && observerMethods.contains(injectionPoint.getTarget().asMethod())) { + if (injectionPoint.getAnnotationTarget().kind().equals(METHOD_PARAMETER) + && observerMethods.contains(injectionPoint.getAnnotationTarget().asMethodParameter().method())) { configProperties .produce(ConfigPropertyBuildItem.staticInit(propertyName, injectedType, propertyDefaultValue)); } @@ -405,19 +406,17 @@ void validateConfigMappingsInjectionPoints( Type type = Type.create(injectionPoint.getRequiredType().name(), Type.Kind.CLASS); ConfigClassBuildItem configClass = configMappingTypes.get(type); if (configClass != null) { - AnnotationTarget target = injectionPoint.getTarget(); + AnnotationTarget target = injectionPoint.getAnnotationTarget(); AnnotationInstance mapping = null; if (target.kind().equals(FIELD)) { mapping = target.asField().annotation(CONFIG_MAPPING_NAME); - } else if (target.kind().equals(METHOD)) { - List parameters = target.asMethod().parameterTypes(); - for (int i = 0; i < parameters.size(); i++) { - Type parameter = parameters.get(i); - if (parameter.name().equals(type.name())) { - Set parameterAnnotations = getParameterAnnotations( - validationPhase.getBeanProcessor().getBeanDeployment(), target.asMethod(), i); - mapping = Annotations.find(parameterAnnotations, CONFIG_MAPPING_NAME); - } + } else if (target.kind().equals(METHOD_PARAMETER)) { + MethodParameterInfo methodParameterInfo = target.asMethodParameter(); + if (methodParameterInfo.type().name().equals(type.name())) { + Set parameterAnnotations = getParameterAnnotations( + validationPhase.getBeanProcessor().getBeanDeployment(), + target.asMethodParameter().method(), methodParameterInfo.position()); + mapping = Annotations.find(parameterAnnotations, CONFIG_MAPPING_NAME); } } diff --git a/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/GrpcClientProcessor.java b/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/GrpcClientProcessor.java index e66fef8f2e7ef..c88d1b4b995d3 100644 --- a/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/GrpcClientProcessor.java +++ b/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/GrpcClientProcessor.java @@ -346,21 +346,17 @@ public void transform(TransformationContext ctx) { AnnotationInstance clientAnnotation = Annotations.find(ctx.getQualifiers(), GrpcDotNames.GRPC_CLIENT); if (clientAnnotation != null && clientAnnotation.value() == null) { String clientName = null; - AnnotationTarget annotationTarget = ctx.getTarget(); - if (ctx.getTarget().kind() == Kind.FIELD) { + AnnotationTarget annotationTarget = ctx.getAnnotationTarget(); + if (ctx.getAnnotationTarget().kind() == Kind.FIELD) { clientName = clientAnnotation.target().asField().name(); - } else if (ctx.getTarget().kind() == Kind.METHOD - && clientAnnotation.target().kind().equals(Kind.METHOD_PARAMETER)) { + } else if (annotationTarget.kind() == Kind.METHOD_PARAMETER) { MethodParameterInfo param = clientAnnotation.target().asMethodParameter(); - annotationTarget = param; // We don't need to check if parameter names are recorded - that's validated elsewhere clientName = param.method().parameterName(param.position()); } if (clientName != null) { ctx.transform().remove(GrpcDotNames::isGrpcClient) - .add(AnnotationInstance.builder(GrpcDotNames.GRPC_CLIENT) - .value(clientName) - .buildWithTarget(annotationTarget)) + .add(AnnotationInstance.builder(GrpcDotNames.GRPC_CLIENT).value(clientName).build()) .done(); } } diff --git a/extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java b/extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java index 67282afd1c3db..39b225344a89d 100644 --- a/extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java +++ b/extensions/qute/deployment/src/main/java/io/quarkus/qute/deployment/QuteProcessor.java @@ -3341,10 +3341,10 @@ static void collectNamespaceExpressions(Expression expression, Set n public static String getName(InjectionPointInfo injectionPoint) { if (injectionPoint.isField()) { - return injectionPoint.getTarget().asField().name(); + return injectionPoint.getAnnotationTarget().asField().name(); } else if (injectionPoint.isParam()) { - String name = injectionPoint.getTarget().asMethod().parameterName(injectionPoint.getPosition()); - return name == null ? injectionPoint.getTarget().asMethod().name() : name; + String name = injectionPoint.getAnnotationTarget().asMethodParameter().name(); + return name == null ? injectionPoint.getAnnotationTarget().asMethodParameter().method().name() : name; } throw new IllegalArgumentException(); } diff --git a/extensions/security-jpa/deployment/src/main/java/io/quarkus/security/jpa/deployment/QuarkusSecurityJpaProcessor.java b/extensions/security-jpa/deployment/src/main/java/io/quarkus/security/jpa/deployment/QuarkusSecurityJpaProcessor.java index a3a892bfe8399..39960d1f3188c 100644 --- a/extensions/security-jpa/deployment/src/main/java/io/quarkus/security/jpa/deployment/QuarkusSecurityJpaProcessor.java +++ b/extensions/security-jpa/deployment/src/main/java/io/quarkus/security/jpa/deployment/QuarkusSecurityJpaProcessor.java @@ -99,8 +99,8 @@ public boolean appliesTo(Type requiredType) { } public void transform(TransformationContext context) { - if (context.getTarget().kind() == AnnotationTarget.Kind.FIELD) { - var declaringClassName = context.getTarget().asField().declaringClass().name(); + if (context.getAnnotationTarget().kind() == AnnotationTarget.Kind.FIELD) { + var declaringClassName = context.getAnnotationTarget().asField().declaringClass().name(); if (JPA_IDENTITY_PROVIDER_NAME.equals(declaringClassName) || JPA_TRUSTED_IDENTITY_PROVIDER_NAME.equals(declaringClassName)) { context.transform() diff --git a/extensions/smallrye-context-propagation/deployment/src/main/java/io/quarkus/smallrye/context/deployment/SmallRyeContextPropagationProcessor.java b/extensions/smallrye-context-propagation/deployment/src/main/java/io/quarkus/smallrye/context/deployment/SmallRyeContextPropagationProcessor.java index 341986949891a..45adb3054a3b9 100644 --- a/extensions/smallrye-context-propagation/deployment/src/main/java/io/quarkus/smallrye/context/deployment/SmallRyeContextPropagationProcessor.java +++ b/extensions/smallrye-context-propagation/deployment/src/main/java/io/quarkus/smallrye/context/deployment/SmallRyeContextPropagationProcessor.java @@ -3,7 +3,6 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -135,67 +134,40 @@ public void transform(TransformationContext transformationContext) { && !ann.name().equals(io.quarkus.arc.processor.DotNames.DEFAULT))) { return; } - AnnotationTarget target = transformationContext.getTarget(); + AnnotationTarget target = transformationContext.getAnnotationTarget(); + AnnotationInstance meConfigInstance = Annotations.find( + transformationContext.getAllTargetAnnotations(), + DotNames.MANAGED_EXECUTOR_CONFIG); + AnnotationInstance tcConfigInstance = Annotations.find( + transformationContext.getAllTargetAnnotations(), + DotNames.THREAD_CONTEXT_CONFIG); + String mpConfigIpName = null; if (target.kind().equals(AnnotationTarget.Kind.FIELD)) { - AnnotationInstance meConfigInstance = Annotations.find(transformationContext.getAllAnnotations(), - DotNames.MANAGED_EXECUTOR_CONFIG); - AnnotationInstance tcConfigInstance = Annotations.find(transformationContext.getAllAnnotations(), - DotNames.THREAD_CONTEXT_CONFIG); - if (meConfigInstance != null || tcConfigInstance != null) { // create a unique name based on the injection point - String mpConfigIpName = target.asField().declaringClass().name().toString() + mpConfigIpName = target.asField().declaringClass().name().toString() + NAME_DELIMITER + target.asField().name(); - - // add @NamedInstance with the generated name - transformationContext.transform() - .add(DotNames.NAMED_INSTANCE, AnnotationValue.createStringValue("value", mpConfigIpName)) - .done(); } - } else if (target.kind().equals(AnnotationTarget.Kind.METHOD)) { - // If it's method, we can have multiple parameters that we might need to configure and - // each injection point needs its own unique @NamedInstance. - // Finally, we register these annotation instance with the transformer. Note that when creating - // each annotation instance, we have to use AnnotationTarget of the _method parameter_ - Collection annotationsToAdd = new ArrayList<>(); - createRequiredAnnotationInstances(Annotations.getAnnotations(AnnotationTarget.Kind.METHOD_PARAMETER, - DotNames.MANAGED_EXECUTOR_CONFIG, transformationContext.getAllAnnotations()), - transformationContext.getQualifiers(), annotationsToAdd); - createRequiredAnnotationInstances(Annotations.getAnnotations(AnnotationTarget.Kind.METHOD_PARAMETER, - DotNames.THREAD_CONTEXT_CONFIG, transformationContext.getAllAnnotations()), - transformationContext.getQualifiers(), annotationsToAdd); - transformationContext.transform().addAll(annotationsToAdd).done(); + } else if (target.kind().equals(AnnotationTarget.Kind.METHOD_PARAMETER)) { + if (meConfigInstance != null || tcConfigInstance != null) { + // create a unique name based on the injection point + mpConfigIpName = target.asMethodParameter().method().declaringClass().name().toString() + + NAME_DELIMITER + + target.asMethodParameter().method().name() + + NAME_DELIMITER + + (target.asMethodParameter().position() + 1); + } } - } - }); - } - - private void createRequiredAnnotationInstances(Collection configAnnotationInstances, - Collection knownQualifiers, - Collection instancesToAdd) { - for (AnnotationInstance annotationInstance : configAnnotationInstances) { - if (annotationInstance.target().kind().equals(AnnotationTarget.Kind.METHOD_PARAMETER)) { - MethodParameterInfo methodParameterInfo = annotationInstance.target().asMethodParameter(); - // skip if the method param injection point has custom qualifiers on it (including @NamedInstance) - if (methodParameterInfo.annotations().stream() - .anyMatch(ann -> knownQualifiers.contains(ann) - && !ann.name().equals(io.quarkus.arc.processor.DotNames.ANY) - && !ann.name().equals(io.quarkus.arc.processor.DotNames.DEFAULT))) { - continue; + if (mpConfigIpName != null) { + // add @NamedInstance with the generated name + transformationContext.transform() + .add(DotNames.NAMED_INSTANCE, AnnotationValue.createStringValue("value", mpConfigIpName)) + .done(); } - String mpConfigIpName = methodParameterInfo.method().declaringClass().name().toString() - + NAME_DELIMITER - + methodParameterInfo.method().name() - + NAME_DELIMITER - + (methodParameterInfo.position() + 1); - // create a new AnnotationInstance with annotation target set to the respective _method parameter_ - instancesToAdd.add(AnnotationInstance.builder(DotNames.NAMED_INSTANCE) - .value(mpConfigIpName) - .buildWithTarget(methodParameterInfo)); } - } + }); } @BuildStep @@ -207,7 +179,7 @@ void createSynthBeansForConfiguredInjectionPoints(BuildProducer threadContextMap = new HashMap<>(); Set unconfiguredContextIPs = new HashSet<>(); for (InjectionPointInfo ipInfo : bdFinishedBuildItem.getInjectionPoints()) { - if (AnnotationTarget.Kind.FIELD.equals(ipInfo.getTarget().kind())) { + if (AnnotationTarget.Kind.FIELD.equals(ipInfo.getAnnotationTarget().kind())) { AnnotationInstance namedAnnotation = ipInfo.getRequiredQualifier(DotNames.NAMED_INSTANCE); // only look for IP with @NamedInstance on it because the IP transformation made sure it's there if (namedAnnotation == null) { @@ -220,9 +192,9 @@ void createSynthBeansForConfiguredInjectionPoints(BuildProducer cleared = providersToStringSet(plan.clearedProviders); assertTrue(propagated.isEmpty()); assertTrue(cleared.contains(ThreadContext.CDI)); + + exec = unwrapExecutor(ctorExecutor3); + assertEquals(2, exec.getMaxAsync()); + assertEquals(-1, exec.getMaxQueued()); // default value } } diff --git a/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/WiringHelper.java b/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/WiringHelper.java index f54afe684ac43..4202be7d67d66 100644 --- a/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/WiringHelper.java +++ b/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/WiringHelper.java @@ -264,7 +264,10 @@ static boolean isSynthetic(MethodInfo method) { static Optional getAnnotation(TransformedAnnotationsBuildItem transformedAnnotations, InjectionPointInfo injectionPoint, DotName annotationName) { - Collection annotations = transformedAnnotations.getAnnotations(injectionPoint.getTarget()); + // Query annotations for either field, or whole method + AnnotationTarget annotationTarget = injectionPoint.isField() ? injectionPoint.getAnnotationTarget() + : injectionPoint.getAnnotationTarget().asMethodParameter().method(); + Collection annotations = transformedAnnotations.getAnnotations(annotationTarget); for (AnnotationInstance annotation : annotations) { if (annotationName.equals(annotation.name())) { // For method parameter we must check the position diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java index 4f93c4bed7548..2e41703a0e002 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanGenerator.java @@ -1795,7 +1795,7 @@ void implementCreateForClassBean(ClassOutput classOutput, ClassCreator beanCreat // We cannot use injectionPoint.getRequiredType() because it might be a resolved parameterize type and we could get NoSuchFieldError tryBlock.writeInstanceField( FieldDescriptor.of(injectedField.declaringClass().name().toString(), injectedField.name(), - DescriptorUtils.typeToString(injectionPoint.getTarget().asField().type())), + DescriptorUtils.typeToString(injectionPoint.getAnnotationTarget().asField().type())), instanceHandle, referenceHandle); } CatchBlockCreator catchBlock = tryBlock.addCatch(RuntimeException.class); @@ -2288,13 +2288,13 @@ public static ResultHandle getJavaMemberHandle(MethodCreator bytecode, Injection if (injectionPoint.isSynthetic()) { javaMemberHandle = bytecode.loadNull(); } else if (injectionPoint.isField()) { - FieldInfo field = injectionPoint.getTarget().asField(); + FieldInfo field = injectionPoint.getAnnotationTarget().asField(); javaMemberHandle = bytecode.invokeStaticMethod(MethodDescriptors.REFLECTIONS_FIND_FIELD, bytecode.loadClass(field.declaringClass().name().toString()), bytecode.load(field.name())); reflectionRegistration.registerField(field); } else { - MethodInfo method = injectionPoint.getTarget().asMethod(); + MethodInfo method = injectionPoint.getAnnotationTarget().asMethodParameter().method(); reflectionRegistration.registerMethod(method); if (method.name().equals(Methods.INIT)) { // Reflections.findConstructor(org.foo.SimpleBean.class,java.lang.String.class) @@ -2333,11 +2333,11 @@ public static ResultHandle collectInjectionPointAnnotations(BeanDeployment beanD } ResultHandle annotationsHandle = bytecode.newInstance(MethodDescriptor.ofConstructor(HashSet.class)); Collection annotations; - if (Kind.FIELD.equals(injectionPoint.getTarget().kind())) { - FieldInfo field = injectionPoint.getTarget().asField(); + if (Kind.FIELD.equals(injectionPoint.getAnnotationTarget().kind())) { + FieldInfo field = injectionPoint.getAnnotationTarget().asField(); annotations = beanDeployment.getAnnotations(field); } else { - MethodInfo method = injectionPoint.getTarget().asMethod(); + MethodInfo method = injectionPoint.getAnnotationTarget().asMethodParameter().method(); annotations = Annotations.getParameterAnnotations(beanDeployment, method, injectionPoint.getPosition()); } diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BuiltinBean.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BuiltinBean.java index f8f3c8865f908..46f2029b164e7 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BuiltinBean.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BuiltinBean.java @@ -371,9 +371,9 @@ private static void generateListBytecode(GeneratorContext ctx) { // Register injection point for reflection InjectionPointInfo injectionPoint = ctx.injectionPoint; if (injectionPoint.isField()) { - ctx.reflectionRegistration.registerField(injectionPoint.getTarget().asField()); + ctx.reflectionRegistration.registerField(injectionPoint.getAnnotationTarget().asField()); } else { - ctx.reflectionRegistration.registerMethod(injectionPoint.getTarget().asMethod()); + ctx.reflectionRegistration.registerMethod(injectionPoint.getAnnotationTarget().asMethodParameter().method()); } MethodCreator mc = ctx.constructor; @@ -464,9 +464,9 @@ private static void validateList(InjectionTargetInfo injectionTarget, InjectionP if (typeParam.kind() == Type.Kind.WILDCARD_TYPE) { ClassInfo declaringClass; if (injectionPoint.isField()) { - declaringClass = injectionPoint.getTarget().asField().declaringClass(); + declaringClass = injectionPoint.getAnnotationTarget().asField().declaringClass(); } else { - declaringClass = injectionPoint.getTarget().asMethod().declaringClass(); + declaringClass = injectionPoint.getAnnotationTarget().asMethodParameter().method().declaringClass(); } if (isKotlinClass(declaringClass)) { errors.accept( diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java index 8fd934b1b255b..76daa01ec7985 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Injection.java @@ -90,18 +90,18 @@ private static void validateInjections(InjectionPointInfo injectionPointInfo, Be && injectionPointInfo.getRequiredType().asParameterizedType().arguments().size() == 1 && injectionPointInfo.hasDefaultedQualifier()) { Type actualType = injectionPointInfo.getRequiredType().asParameterizedType().arguments().get(0); - AnnotationTarget ipTarget = injectionPointInfo.getTarget(); + AnnotationTarget ipTarget = injectionPointInfo.getAnnotationTarget(); DotName expectedType = null; if (ipTarget.kind() == Kind.FIELD) { // field injection derives this from the class expectedType = ipTarget.asField().declaringClass().name(); - } else if (ipTarget.kind() == Kind.METHOD) { + } else if (ipTarget.kind() == Kind.METHOD_PARAMETER) { // the injection point is a producer method parameter then the type parameter of the injected Bean // must be the same as the producer method return type if (beanType == BeanType.PRODUCER_METHOD) { - expectedType = ipTarget.asMethod().returnType().name(); + expectedType = ipTarget.asMethodParameter().method().returnType().name(); } else { - expectedType = ipTarget.asMethod().declaringClass().name(); + expectedType = ipTarget.asMethodParameter().method().declaringClass().name(); } } if (expectedType != null @@ -137,12 +137,12 @@ private static void validateInjections(InjectionPointInfo injectionPointInfo, Be && injectionPointInfo.getRequiredType().kind() == Type.Kind.PARAMETERIZED_TYPE && injectionPointInfo.getRequiredType().asParameterizedType().arguments().size() == 1) { Type actualType = injectionPointInfo.getRequiredType().asParameterizedType().arguments().get(0); - AnnotationTarget ipTarget = injectionPointInfo.getTarget(); + AnnotationTarget ipTarget = injectionPointInfo.getAnnotationTarget(); DotName expectedType = null; if (ipTarget.kind() == Kind.FIELD) { expectedType = ipTarget.asField().declaringClass().name(); - } else if (ipTarget.kind() == Kind.METHOD) { - expectedType = ipTarget.asMethod().declaringClass().name(); + } else if (ipTarget.kind() == Kind.METHOD_PARAMETER) { + expectedType = ipTarget.asMethodParameter().method().declaringClass().name(); } if (expectedType != null // This is very rudimentary check, might need to be expanded? 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 f38cc68397816..3960051e04b96 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 @@ -713,10 +713,10 @@ static Set getDelegateTypeClosure(InjectionPointInfo delegateInjectionPoin throw new IllegalArgumentException("Delegate type not found in index: " + delegateType); } if (Kind.CLASS.equals(delegateType.kind())) { - types = getTypeClosure(delegateTypeClass, delegateInjectionPoint.getTarget(), Collections.emptyMap(), + types = getTypeClosure(delegateTypeClass, delegateInjectionPoint.getAnnotationTarget(), Collections.emptyMap(), beanDeployment, null, unrestrictedBeanTypes); } else if (Kind.PARAMETERIZED_TYPE.equals(delegateType.kind())) { - types = getTypeClosure(delegateTypeClass, delegateInjectionPoint.getTarget(), + types = getTypeClosure(delegateTypeClass, delegateInjectionPoint.getAnnotationTarget(), buildResolvedMap(delegateType.asParameterizedType().arguments(), delegateTypeClass.typeParameters(), Collections.emptyMap(), beanDeployment.getBeanArchiveIndex()), beanDeployment, null, unrestrictedBeanTypes); diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/bcextensions/InjectionPointInfoImpl.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/bcextensions/InjectionPointInfoImpl.java index a4f99e34b50aa..433fa0d6351e4 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/bcextensions/InjectionPointInfoImpl.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/bcextensions/InjectionPointInfoImpl.java @@ -35,14 +35,11 @@ public Collection qualifiers() { @Override public DeclarationInfo declaration() { if (arcInjectionPointInfo.isField()) { - org.jboss.jandex.FieldInfo jandexField = arcInjectionPointInfo.getTarget().asField(); + org.jboss.jandex.FieldInfo jandexField = arcInjectionPointInfo.getAnnotationTarget().asField(); return new FieldInfoImpl(jandexIndex, annotationOverlay, jandexField); } else if (arcInjectionPointInfo.isParam()) { - org.jboss.jandex.MethodInfo jandexMethod = arcInjectionPointInfo.getTarget().asMethod(); - int parameterPosition = arcInjectionPointInfo.getPosition(); - org.jboss.jandex.MethodParameterInfo jandexParameter = org.jboss.jandex.MethodParameterInfo.create( - jandexMethod, (short) parameterPosition); - return new ParameterInfoImpl(jandexIndex, annotationOverlay, jandexParameter); + return new ParameterInfoImpl(jandexIndex, annotationOverlay, + arcInjectionPointInfo.getAnnotationTarget().asMethodParameter()); } else { throw new IllegalStateException("Unknown injection point: " + arcInjectionPointInfo); } diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/buildextension/injectionPoints/InjectionPointTransformerTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/buildextension/injectionPoints/InjectionPointTransformerTest.java index 807773e9b7948..bae693d0fe007 100644 --- a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/buildextension/injectionPoints/InjectionPointTransformerTest.java +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/buildextension/injectionPoints/InjectionPointTransformerTest.java @@ -54,6 +54,7 @@ public void testQualifierWasAddedToInjectionPoint() { Arc.container().beanManager().getEvent().select(Integer.class).fire(42); CasualObserver observer = arc.instance(CasualObserver.class).get(); assertEquals("bar", observer.getChangedString()); + assertEquals("foo", observer.getChanged2String()); assertEquals("foo", observer.getUnchangedString()); } @@ -103,11 +104,14 @@ public String getFoo() { static class CasualObserver { String changeMe; + String changeMe2; String dontChangeMe; // there is no String with qualifier @AnotherQualifier, we will remove it - public void observe(@Observes Integer payload, @AnotherQualifier String changeMe, @MyQualifier String dontChangeMe) { + public void observe(@Observes Integer payload, @AnotherQualifier String changeMe, @MyQualifier String dontChangeMe, + String changeMe2) { this.changeMe = changeMe; + this.changeMe2 = changeMe2; this.dontChangeMe = dontChangeMe; } @@ -115,6 +119,10 @@ public String getChangedString() { return changeMe; } + public String getChanged2String() { + return changeMe2; + } + public String getUnchangedString() { return dontChangeMe; } @@ -130,25 +138,29 @@ public boolean appliesTo(Type requiredType) { @Override public void transform(TransformationContext transformationContext) { - AnnotationTarget.Kind kind = transformationContext.getTarget().kind(); + AnnotationTarget.Kind kind = transformationContext.getAnnotationTarget().kind(); if (AnnotationTarget.Kind.FIELD.equals(kind)) { - FieldInfo fieldInfo = transformationContext.getTarget().asField(); + FieldInfo fieldInfo = transformationContext.getAnnotationTarget().asField(); // with this we should be able to filter out only fields we want to affect if (fieldInfo.declaringClass().name().equals(DotName.createSimple(SimpleConsumer.class.getName())) && fieldInfo.name().equals("foo")) { transformationContext.transform().add(MyQualifier.class).done(); } - } else if (AnnotationTarget.Kind.METHOD.equals(kind)) { - MethodInfo methodInfo = transformationContext.getTarget().asMethod(); + } else if (AnnotationTarget.Kind.METHOD_PARAMETER.equals(kind)) { + MethodInfo methodInfo = transformationContext.getAnnotationTarget().asMethodParameter().method(); DotName anotherQualifierDotName = DotName.createSimple(AnotherQualifier.class.getName()); if (methodInfo.declaringClass().name() - .equals(DotName.createSimple(CasualObserver.class.getName())) - && transformationContext.getAllAnnotations().stream() - .anyMatch(p -> p.name().equals(anotherQualifierDotName))) { - transformationContext.transform() - .remove(annotationInstance -> annotationInstance.name().equals(anotherQualifierDotName)) - .done(); + .equals(DotName.createSimple(CasualObserver.class.getName()))) { + if (transformationContext.getAllTargetAnnotations().stream() + .anyMatch(p -> p.name().equals(anotherQualifierDotName))) { + transformationContext.transform() + .remove(annotationInstance -> annotationInstance.name().equals(anotherQualifierDotName)) + .done(); + } else if (transformationContext.getAllTargetAnnotations().isEmpty()) { + transformationContext.transform().add(MyQualifier.class).done(); + } + } } else { throw new IllegalStateException("Unexpected injection point kind: " + kind); diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/buildextension/validator/BeanDeploymentValidatorTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/buildextension/validator/BeanDeploymentValidatorTest.java index 44b5407a80a7f..768f48cfa8ed0 100644 --- a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/buildextension/validator/BeanDeploymentValidatorTest.java +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/buildextension/validator/BeanDeploymentValidatorTest.java @@ -62,8 +62,8 @@ static class TestValidator implements BeanDeploymentValidator { @Override public void validate(ValidationContext context) { assertTrue(context.getInjectionPoints().stream().filter(InjectionPointInfo::isProgrammaticLookup) - .filter(ip -> ip.getTarget().kind() == org.jboss.jandex.AnnotationTarget.Kind.FIELD - && ip.getTarget().asField().name().equals("foo")) + .filter(ip -> ip.getAnnotationTarget().kind() == org.jboss.jandex.AnnotationTarget.Kind.FIELD + && ip.getAnnotationTarget().asField().name().equals("foo")) .findFirst().isPresent()); assertFalse(context.removedBeans().withBeanClass(UselessBean.class).isEmpty()); diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/injection/resource/ResourceInjectionTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/injection/resource/ResourceInjectionTest.java index ecef3af79b7fa..49fa96a192093 100644 --- a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/injection/resource/ResourceInjectionTest.java +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/injection/resource/ResourceInjectionTest.java @@ -62,7 +62,7 @@ public boolean appliesTo(org.jboss.jandex.Type requiredType) { @Override public void transform(TransformationContext transformationContext) { - if (transformationContext.getAllAnnotations() + if (transformationContext.getAllTargetAnnotations() .stream() .anyMatch(it -> it.name().toString().equals(Dummy.class.getName()))) { // pretend that the injection point has an annotation whose class is missing From 1b3b935e2e5ce6eb5d19b6f933b4a91c3e9f7a26 Mon Sep 17 00:00:00 2001 From: Matej Novotny Date: Tue, 4 Jun 2024 14:25:35 +0200 Subject: [PATCH 3/3] Change TransformedAnnotationsBuildItem to account for AnnotationTarget being a method parameter --- .../TransformedAnnotationsBuildItem.java | 50 +++++++++++++++++-- .../deployment/WiringHelper.java | 19 ++----- 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/TransformedAnnotationsBuildItem.java b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/TransformedAnnotationsBuildItem.java index 2e7bc1754e7cb..6fdcbdab396dc 100644 --- a/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/TransformedAnnotationsBuildItem.java +++ b/extensions/arc/deployment/src/main/java/io/quarkus/arc/deployment/TransformedAnnotationsBuildItem.java @@ -1,6 +1,7 @@ package io.quarkus.arc.deployment; import java.lang.annotation.Annotation; +import java.util.ArrayList; import java.util.Collection; import java.util.function.Function; @@ -27,11 +28,15 @@ public final class TransformedAnnotationsBuildItem extends SimpleBuildItem } public Collection getAnnotations(AnnotationTarget target) { - return beanDeployment.getAnnotations(target); + return queryAndConditionallyFilter(target); } public AnnotationInstance getAnnotation(AnnotationTarget target, DotName annotationName) { - return beanDeployment.getAnnotation(target, annotationName); + if (target.kind().equals(AnnotationTarget.Kind.METHOD_PARAMETER)) { + return queryForMethodParam(target, annotationName); + } else { + return beanDeployment.getAnnotation(target, annotationName); + } } public AnnotationInstance getAnnotation(AnnotationTarget target, Class annotationClass) { @@ -39,7 +44,11 @@ public AnnotationInstance getAnnotation(AnnotationTarget target, Class annotationClass) { @@ -48,7 +57,40 @@ public boolean hasAnnotation(AnnotationTarget target, Class apply(AnnotationTarget target) { - return beanDeployment.getAnnotations(target); + return queryAndConditionallyFilter(target); } + private Collection queryAndConditionallyFilter(AnnotationTarget target) { + if (target.kind().equals(AnnotationTarget.Kind.METHOD_PARAMETER)) { + // We cannot query Jandex for method param. annotation target, so we operate on the whole method + // and filter results accordingly + Collection result = new ArrayList<>(); + for (AnnotationInstance instance : beanDeployment.getAnnotations(target.asMethodParameter().method())) { + if (instance.target().kind().equals(AnnotationTarget.Kind.METHOD_PARAMETER) + && instance.target().asMethodParameter().position() == target.asMethodParameter().position()) { + result.add(instance); + } + } + return result; + } else { + return beanDeployment.getAnnotations(target); + } + } + + private AnnotationInstance queryForMethodParam(AnnotationTarget target, DotName annotationName) { + if (!target.kind().equals(AnnotationTarget.Kind.METHOD_PARAMETER)) { + throw new IllegalArgumentException( + "TransformedAnnotationsBuildItem#queryForMethodParam needs to operate on METHOD_PARAMETER AnnotationTarget"); + } + // We cannot query Jandex for method param. annotation target, so we operate on the whole method + // and filter results accordingly + for (AnnotationInstance instance : beanDeployment.getAnnotations(target.asMethodParameter().method())) { + if (instance.name().equals(annotationName) + && instance.target().kind().equals(AnnotationTarget.Kind.METHOD_PARAMETER) + && instance.target().asMethodParameter().position() == target.asMethodParameter().position()) { + return instance; + } + } + return null; + } } diff --git a/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/WiringHelper.java b/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/WiringHelper.java index 4202be7d67d66..b42927e327771 100644 --- a/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/WiringHelper.java +++ b/extensions/smallrye-reactive-messaging/deployment/src/main/java/io/quarkus/smallrye/reactivemessaging/deployment/WiringHelper.java @@ -11,7 +11,6 @@ import org.eclipse.microprofile.config.ConfigProvider; 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; @@ -264,21 +263,13 @@ static boolean isSynthetic(MethodInfo method) { static Optional getAnnotation(TransformedAnnotationsBuildItem transformedAnnotations, InjectionPointInfo injectionPoint, DotName annotationName) { - // Query annotations for either field, or whole method - AnnotationTarget annotationTarget = injectionPoint.isField() ? injectionPoint.getAnnotationTarget() - : injectionPoint.getAnnotationTarget().asMethodParameter().method(); - Collection annotations = transformedAnnotations.getAnnotations(annotationTarget); + // For field IP -> set of field annotations + // For method param IP -> set of param annotations + Collection annotations = transformedAnnotations + .getAnnotations(injectionPoint.getAnnotationTarget()); for (AnnotationInstance annotation : annotations) { if (annotationName.equals(annotation.name())) { - // For method parameter we must check the position - if (annotation.target().kind() == AnnotationTarget.Kind.METHOD_PARAMETER - && injectionPoint.isParam() - && annotation.target().asMethodParameter().position() == injectionPoint.getPosition()) { - return Optional.of(annotation); - } else if (annotation.target().kind() != AnnotationTarget.Kind.METHOD_PARAMETER) { - // For other kind, no need to check anything else - return Optional.of(annotation); - } + return Optional.of(annotation); } } return Optional.empty();