From 7a0ee7ac0a3e71bca7921d6d8f09090ef6fcc4a7 Mon Sep 17 00:00:00 2001 From: Martin Kouba Date: Thu, 10 Jun 2021 16:03:38 +0200 Subject: [PATCH] Change the behavior of InjectionPointInfo.getRequiredType() - InjectionPointInfo.getRequiredType() should return the type parameter for programmatic lookup - resolves #17835 --- .../arc/deployment/ConfigBuildStep.java | 24 ++++++++-------- .../grpc/deployment/GrpcClientProcessor.java | 6 ---- .../jwt/deployment/SmallRyeJwtProcessor.java | 4 +-- .../quarkus/arc/processor/BeanDeployment.java | 2 +- .../quarkus/arc/processor/BeanGenerator.java | 10 +++---- .../quarkus/arc/processor/BeanRegistrar.java | 5 ++++ .../java/io/quarkus/arc/processor/Beans.java | 4 +-- .../io/quarkus/arc/processor/BuiltinBean.java | 8 +++--- .../arc/processor/InjectionPointInfo.java | 28 +++++++++++++++++++ .../arc/processor/ObserverGenerator.java | 2 +- .../arc/processor/SubclassGenerator.java | 2 +- .../BeanDeploymentValidatorTest.java | 10 +++++++ 12 files changed, 71 insertions(+), 34 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 ca683d5545aeb..a4a7598e028a4 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 @@ -120,19 +120,19 @@ void analyzeConfigPropertyInjectionPoints(BeanDiscoveryFinishedBuildItem beanDis } // Register a custom bean for injection points that are not handled by ConfigProducer - Type requiredType = injectionPoint.getRequiredType(); - if (!isHandledByProducers(requiredType)) { - customBeanTypes.add(requiredType); + Type injectedType = injectionPoint.getType(); + if (!isHandledByProducers(injectedType)) { + customBeanTypes.add(injectedType); } - if (DotNames.OPTIONAL.equals(requiredType.name()) - || DotNames.OPTIONAL_INT.equals(requiredType.name()) - || DotNames.OPTIONAL_LONG.equals(requiredType.name()) - || DotNames.OPTIONAL_DOUBLE.equals(requiredType.name()) - || DotNames.PROVIDER.equals(requiredType.name()) - || SUPPLIER_NAME.equals(requiredType.name()) - || CONFIG_VALUE_NAME.equals(requiredType.name()) - || MP_CONFIG_VALUE_NAME.equals(requiredType.name())) { + if (DotNames.OPTIONAL.equals(injectedType.name()) + || DotNames.OPTIONAL_INT.equals(injectedType.name()) + || DotNames.OPTIONAL_LONG.equals(injectedType.name()) + || DotNames.OPTIONAL_DOUBLE.equals(injectedType.name()) + || DotNames.PROVIDER.equals(injectedType.name()) + || SUPPLIER_NAME.equals(injectedType.name()) + || CONFIG_VALUE_NAME.equals(injectedType.name()) + || MP_CONFIG_VALUE_NAME.equals(injectedType.name())) { // Never validate container objects continue; } @@ -143,7 +143,7 @@ void analyzeConfigPropertyInjectionPoints(BeanDiscoveryFinishedBuildItem beanDis propertyDefaultValue = defaultValue.asString(); } - configProperties.produce(new ConfigPropertyBuildItem(propertyName, requiredType, propertyDefaultValue)); + configProperties.produce(new ConfigPropertyBuildItem(propertyName, injectedType, propertyDefaultValue)); } } 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 b2723fb9d838f..7d529d1d25cbb 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 @@ -143,12 +143,6 @@ void discoverInjectedGrpcServices(BeanDiscoveryFinishedBuildItem beanDiscovery, } Type injectionType = injectionPoint.getRequiredType(); - - // Programmatic lookup - take the param type - if (DotNames.INSTANCE.equals(injectionType.name()) || DotNames.INJECTABLE_INSTANCE.equals(injectionType.name())) { - injectionType = injectionType.asParameterizedType().arguments().get(0); - } - if (injectionType.name().equals(GrpcDotNames.CHANNEL)) { // No need to add the stub class for Channel continue; diff --git a/extensions/smallrye-jwt/deployment/src/main/java/io/quarkus/smallrye/jwt/deployment/SmallRyeJwtProcessor.java b/extensions/smallrye-jwt/deployment/src/main/java/io/quarkus/smallrye/jwt/deployment/SmallRyeJwtProcessor.java index bd16b00fff713..94cbc5db38180 100644 --- a/extensions/smallrye-jwt/deployment/src/main/java/io/quarkus/smallrye/jwt/deployment/SmallRyeJwtProcessor.java +++ b/extensions/smallrye-jwt/deployment/src/main/java/io/quarkus/smallrye/jwt/deployment/SmallRyeJwtProcessor.java @@ -138,9 +138,9 @@ void registerOptionalClaimProducer(BeanRegistrationPhaseBuildItem beanRegistrati continue; } AnnotationInstance claimQualifier = injectionPoint.getRequiredQualifier(CLAIM_NAME); - if (claimQualifier != null && injectionPoint.getRequiredType().name().equals(DotNames.PROVIDER)) { + if (claimQualifier != null && injectionPoint.getType().name().equals(DotNames.PROVIDER)) { // Classes from javax.json are handled specially - Type actualType = injectionPoint.getRequiredType().asParameterizedType().arguments().get(0); + Type actualType = injectionPoint.getRequiredType(); if (actualType.name().equals(DotNames.OPTIONAL) && !actualType.name().toString() .startsWith("javax.json")) { additionalTypes.add(actualType); diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java index 27a59755be1d6..7b264a846fac4 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java @@ -307,7 +307,7 @@ void init(Consumer bytecodeTransformerConsumer, // Instance for (InjectionPointInfo injectionPoint : instanceInjectionPoints) { if (Beans.hasQualifiers(bean, injectionPoint.getRequiredQualifiers()) && Beans.matchesType(bean, - injectionPoint.getRequiredType().asParameterizedType().arguments().get(0))) { + injectionPoint.getType().asParameterizedType().arguments().get(0))) { continue test; } } 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 abec759713caa..38479d4a97b58 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 @@ -1007,7 +1007,7 @@ private ResultHandle newInstanceHandle(BeanInfo bean, ClassCreator beanCreator, // 1. constructor injection points for (int i = 0; i < injectionPoints.size(); i++) { - paramTypes.add(injectionPoints.get(i).getRequiredType().name().toString()); + paramTypes.add(injectionPoints.get(i).getType().name().toString()); paramHandles.add(providerHandles.get(i)); } // 2. ctx @@ -1038,7 +1038,7 @@ private ResultHandle newInstanceHandle(BeanInfo bean, ClassCreator beanCreator, ResultHandle argsArray = creator.newArray(Object.class, creator.load(providerHandles.size())); for (int i = 0; i < injectionPoints.size(); i++) { creator.writeArrayValue(paramTypesArray, i, - creator.loadClass(injectionPoints.get(i).getRequiredType().name().toString())); + creator.loadClass(injectionPoints.get(i).getType().name().toString())); creator.writeArrayValue(argsArray, i, providerHandles.get(i)); } registration.registerMethod(constructor); @@ -1050,7 +1050,7 @@ private ResultHandle newInstanceHandle(BeanInfo bean, ClassCreator beanCreator, String[] paramTypes = new String[injectionPoints.size()]; for (ListIterator iterator = injectionPoints.listIterator(); iterator.hasNext();) { InjectionPointInfo injectionPoint = iterator.next(); - paramTypes[iterator.previousIndex()] = DescriptorUtils.typeToString(injectionPoint.getRequiredType()); + paramTypes[iterator.previousIndex()] = DescriptorUtils.typeToString(injectionPoint.getType()); } return creator.newInstance(MethodDescriptor.ofConstructor(providerTypeName, paramTypes), providerHandles.toArray(new ResultHandle[0])); @@ -1350,7 +1350,7 @@ void implementCreateForClassBean(ClassOutput classOutput, ClassCreator beanCreat if (constructorInjection.isPresent()) { List paramTypes = new ArrayList<>(); for (InjectionPointInfo injectionPoint : constructorInjection.get().injectionPoints) { - paramTypes.add(injectionPoint.getRequiredType().name().toString()); + paramTypes.add(injectionPoint.getType().name().toString()); } ResultHandle[] paramsHandles = new ResultHandle[2]; paramsHandles[0] = create.loadClass(providerType.className()); @@ -1794,7 +1794,7 @@ private ResultHandle wrapCurrentInjectionPoint(ClassOutput classOutput, ClassCre Supplier.class, java.lang.reflect.Type.class, Set.class, Set.class, Member.class, int.class), constructor.getThis(), constructor.getMethodParam(paramIdx), - Types.getTypeHandle(constructor, injectionPoint.getRequiredType(), tccl), + Types.getTypeHandle(constructor, injectionPoint.getType(), tccl), requiredQualifiersHandle, annotationsHandle, javaMemberHandle, constructor.load(injectionPoint.getPosition())); } diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanRegistrar.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanRegistrar.java index 53c0057364a16..38a282cc94a6a 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanRegistrar.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanRegistrar.java @@ -1,5 +1,6 @@ package io.quarkus.arc.processor; +import java.util.Collection; import org.jboss.jandex.DotName; /** @@ -45,6 +46,10 @@ default BeanConfigurator configure(Class beanClass) { */ BeanStream beans(); + default Collection getInjectionPoints() { + return get(BuildExtension.Key.INJECTION_POINTS); + } + } } diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Beans.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Beans.java index 8e3a960fdc4e9..63c8b7ec367bd 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Beans.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/Beans.java @@ -463,7 +463,7 @@ static void resolveInjectionPoint(BeanDeployment deployment, InjectionTargetInfo errors.add(new DefinitionException("EventMetadata can be only injected into an observer method: " + injectionPoint.getTargetInfo())); } else if (BuiltinBean.INSTANCE == builtinBean - && injectionPoint.getRequiredType().kind() != Kind.PARAMETERIZED_TYPE) { + && injectionPoint.getType().kind() != Kind.PARAMETERIZED_TYPE) { errors.add( new DefinitionException("An injection point of raw type javax.enterprise.inject.Instance is defined: " + injectionPoint.getTargetInfo())); @@ -510,7 +510,7 @@ static void resolveInjectionPoint(BeanDeployment deployment, InjectionTargetInfo private static void addStandardErroneousDependencyMessage(InjectionTargetInfo target, InjectionPointInfo injectionPoint, StringBuilder message) { - message.append(injectionPoint.getRequiredType()); + message.append(injectionPoint.getType()); message.append(" and qualifiers "); message.append(injectionPoint.getRequiredQualifiers()); message.append("\n\t- java member: "); 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 0a056df71f367..3bd1b9c895f56 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 @@ -36,7 +36,7 @@ enum BuiltinBean { ResultHandle qualifiers = BeanGenerator.collectInjectionPointQualifiers(ctx.classOutput, ctx.clazzCreator, ctx.beanDeployment, ctx.constructor, ctx.injectionPoint, ctx.annotationLiterals); - ResultHandle parameterizedType = Types.getTypeHandle(ctx.constructor, ctx.injectionPoint.getRequiredType()); + ResultHandle parameterizedType = Types.getTypeHandle(ctx.constructor, ctx.injectionPoint.getType()); ResultHandle annotationsHandle = BeanGenerator.collectInjectionPointAnnotations(ctx.classOutput, ctx.clazzCreator, ctx.beanDeployment, ctx.constructor, ctx.injectionPoint, ctx.annotationLiterals, ctx.injectionPointAnnotationsPredicate); @@ -149,7 +149,7 @@ enum BuiltinBean { } } } - ResultHandle parameterizedType = Types.getTypeHandle(ctx.constructor, ctx.injectionPoint.getRequiredType()); + ResultHandle parameterizedType = Types.getTypeHandle(ctx.constructor, ctx.injectionPoint.getType()); ResultHandle eventProvider = ctx.constructor.newInstance( MethodDescriptor.ofConstructor(EventProvider.class, java.lang.reflect.Type.class, Set.class), @@ -175,7 +175,7 @@ enum BuiltinBean { Types.getPackageName(ctx.clazzCreator.getClassName()))); } } - ResultHandle parameterizedType = Types.getTypeHandle(ctx.constructor, ctx.injectionPoint.getRequiredType()); + ResultHandle parameterizedType = Types.getTypeHandle(ctx.constructor, ctx.injectionPoint.getType()); ResultHandle resourceProvider = ctx.constructor.newInstance( MethodDescriptor.ofConstructor(ResourceProvider.class, java.lang.reflect.Type.class, Set.class), @@ -283,7 +283,7 @@ private static boolean isCdiAndRawTypeMatches(InjectionPointInfo injectionPoint, return false; } for (DotName rawTypeDotName : rawTypeDotNames) { - if (rawTypeDotName.equals(injectionPoint.getRequiredType().name())) { + if (rawTypeDotName.equals(injectionPoint.getType().name())) { return true; } } 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 c193a29201272..71fed5c07feab 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 @@ -121,10 +121,38 @@ InjectionPointKind getKind() { return kind; } + /** + * Note that for programmatic lookup, the required type is the type parameter specified at the injection point. For example, + * the required type for an injection point of type {@code Instance} is {@code org.acme.Foo}. + * + * @return the required type of this injection point + */ public Type getRequiredType() { + Type requiredType = typeAndQualifiers.type; + if (isProgrammaticLookup() && requiredType.kind() == org.jboss.jandex.Type.Kind.PARAMETERIZED_TYPE) { + requiredType = requiredType.asParameterizedType().arguments().get(0); + } + return requiredType; + } + + /** + * This method always returns the original type declared on the injection point, unlike {@link #getRequiredType()}. + * + * @return the type specified at the injection point + */ + public Type getType() { return typeAndQualifiers.type; } + /** + * @return true if this injection represents a dynamically obtained instance, false otherwise + */ + public boolean isProgrammaticLookup() { + DotName requiredTypeName = typeAndQualifiers.type.name(); + return DotNames.INSTANCE.equals(requiredTypeName) || DotNames.INJECTABLE_INSTANCE.equals(requiredTypeName) + || DotNames.PROVIDER.equals(requiredTypeName); + } + public Set getRequiredQualifiers() { return typeAndQualifiers.qualifiers; } diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ObserverGenerator.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ObserverGenerator.java index e5869a93fc458..bee4cb128f6a1 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ObserverGenerator.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ObserverGenerator.java @@ -517,7 +517,7 @@ protected void createConstructor(ClassOutput classOutput, ClassCreator observerC Supplier.class, java.lang.reflect.Type.class, Set.class, Set.class, Member.class, int.class), constructor.loadNull(), delegateSupplier, - Types.getTypeHandle(constructor, injectionPoint.getRequiredType()), + Types.getTypeHandle(constructor, injectionPoint.getType()), requiredQualifiersHandle, annotationsHandle, javaMemberHandle, constructor.load(injectionPoint.getPosition())); ResultHandle wrapSupplierHandle = constructor.newInstance( 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 52643b268f85e..7aeabdad20908 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 @@ -132,7 +132,7 @@ protected FieldDescriptor createConstructor(ClassOutput classOutput, BeanInfo be Optional constructorInjection = bean.getConstructorInjection(); if (constructorInjection.isPresent()) { for (InjectionPointInfo injectionPoint : constructorInjection.get().injectionPoints) { - parameterTypes.add(injectionPoint.getRequiredType().name().toString()); + parameterTypes.add(injectionPoint.getType().name().toString()); } } int superParamsSize = parameterTypes.size(); 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 fc6018ddb46b2..697f188186964 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 @@ -9,6 +9,7 @@ import io.quarkus.arc.processor.BeanDeploymentValidator; import io.quarkus.arc.processor.BeanInfo; import io.quarkus.arc.processor.BeanRegistrar; +import io.quarkus.arc.processor.InjectionPointInfo; import io.quarkus.arc.processor.ObserverInfo; import io.quarkus.arc.test.ArcTestContainer; import java.util.Collection; @@ -20,6 +21,7 @@ import javax.enterprise.context.Initialized; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.event.Observes; +import javax.enterprise.inject.Instance; import javax.inject.Inject; import javax.inject.Named; import org.jboss.jandex.DotName; @@ -56,6 +58,11 @@ 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")) + .findFirst().isPresent()); + assertFalse(context.removedBeans().withBeanClass(UselessBean.class).isEmpty()); assertFalse(context.beans().classBeans().withBeanClass(Alpha.class).isEmpty()); @@ -88,6 +95,9 @@ static class Alpha { @Inject List strings; + @Inject + Instance foo; + void observeAppContextInit(@Observes @Initialized(ApplicationScoped.class) Object event) { }