From 7c77aa6a470758003cfe13057c8b2168be8bd681 Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Fri, 19 Aug 2022 14:38:42 +0200 Subject: [PATCH] Fix type variable resolution in ArC's bean type closure search --- .../arc/processor/ClientProxyGenerator.java | 7 ++-- .../arc/processor/DecoratorGenerator.java | 4 +- .../arc/processor/InjectionPointInfo.java | 7 ++-- .../quarkus/arc/processor/ObserverInfo.java | 3 +- .../arc/processor/SubclassGenerator.java | 4 +- .../java/io/quarkus/arc/processor/Types.java | 38 ++++++++++--------- .../io/quarkus/arc/processor/TypesTest.java | 5 +-- 7 files changed, 33 insertions(+), 35 deletions(-) diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ClientProxyGenerator.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ClientProxyGenerator.java index 3523648b96b93..e13c36fcebb3b 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ClientProxyGenerator.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/ClientProxyGenerator.java @@ -35,7 +35,6 @@ import org.jboss.jandex.IndexView; import org.jboss.jandex.MethodInfo; import org.jboss.jandex.Type; -import org.jboss.jandex.TypeVariable; /** * @@ -120,7 +119,7 @@ Collection generate(BeanInfo bean, String beanClassName, if (!providerClass.typeParameters().isEmpty()) { clientProxy.setSignature(AsmUtilCopy.getGeneratedSubClassSignature(providerClass, bean.getProviderType())); } - Map> resolvedTypeVariables = Types.resolvedTypeVariables(providerClass, + Map> resolvedTypeVariables = Types.resolvedTypeVariables(providerClass, bean.getDeployment()); FieldCreator beanField = clientProxy.getFieldCreator(BEAN_FIELD, InjectableBean.class) .setModifiers(ACC_PRIVATE | ACC_FINAL); @@ -148,10 +147,10 @@ Collection generate(BeanInfo bean, String beanClassName, MethodDescriptor originalMethodDescriptor = MethodDescriptor.of(method); MethodCreator forward = clientProxy.getMethodCreator(originalMethodDescriptor); if (AsmUtilCopy.needsSignature(method)) { - Map methodClassVariables = resolvedTypeVariables.get(method.declaringClass()); + Map methodClassVariables = resolvedTypeVariables.get(method.declaringClass()); String signature = AsmUtilCopy.getSignature(method, typeVariable -> { if (methodClassVariables != null) { - Type ret = methodClassVariables.get(typeVariable); + Type ret = methodClassVariables.get(typeVariable.identifier()); // let's not map a TV to itself if (ret != typeVariable) return ret; diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/DecoratorGenerator.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/DecoratorGenerator.java index 65fc970d8fece..6091bad566cc4 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/DecoratorGenerator.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/DecoratorGenerator.java @@ -187,7 +187,7 @@ private String generateDecoratorImplementation(String baseName, String targetPac // 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(); + Map resolvedTypeParameters = Collections.emptyMap(); if (!typeParameters.isEmpty()) { resolvedTypeParameters = new HashMap<>(); // The delegate type can be used to infer the parameter types @@ -195,7 +195,7 @@ private String generateDecoratorImplementation(String baseName, String targetPac if (type.kind() == Kind.PARAMETERIZED_TYPE) { List typeArguments = type.asParameterizedType().arguments(); for (int i = 0; i < typeParameters.size(); i++) { - resolvedTypeParameters.put(typeParameters.get(i), typeArguments.get(i)); + resolvedTypeParameters.put(typeParameters.get(i).identifier(), typeArguments.get(i)); } } } 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 1477f06aceedd..2bdf5ea705f41 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 @@ -22,7 +22,6 @@ import org.jboss.jandex.MethodInfo; import org.jboss.jandex.ParameterizedType; import org.jboss.jandex.Type; -import org.jboss.jandex.TypeVariable; /** * Represents an injection point. @@ -262,15 +261,15 @@ private static Type resolveType(Type type, ClassInfo beanClass, ClassInfo declar if (type.kind() == org.jboss.jandex.Type.Kind.CLASS) { return type; } - Map> resolvedTypeVariables = Types.resolvedTypeVariables(beanClass, beanDeployment); + Map> resolvedTypeVariables = Types.resolvedTypeVariables(beanClass, beanDeployment); return resolveType(type, declaringClass, beanDeployment, resolvedTypeVariables); } private static Type resolveType(Type type, ClassInfo beanClass, BeanDeployment beanDeployment, - Map> resolvedTypeVariables) { + Map> resolvedTypeVariables) { if (type.kind() == org.jboss.jandex.Type.Kind.TYPE_VARIABLE) { if (resolvedTypeVariables.containsKey(beanClass)) { - return resolvedTypeVariables.get(beanClass).getOrDefault(type.asTypeVariable(), type); + return resolvedTypeVariables.get(beanClass).getOrDefault(type.asTypeVariable().identifier(), type); } } else if (type.kind() == org.jboss.jandex.Type.Kind.PARAMETERIZED_TYPE) { ParameterizedType parameterizedType = type.asParameterizedType(); 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 6a4579e675011..b858c74df729e 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 @@ -27,7 +27,6 @@ import org.jboss.jandex.MethodInfo; import org.jboss.jandex.MethodParameterInfo; import org.jboss.jandex.Type; -import org.jboss.jandex.TypeVariable; import org.jboss.logging.Logger; /** @@ -54,7 +53,7 @@ static ObserverInfo create(BeanInfo declaringBean, MethodInfo observerMethod, In Type observedType = observerMethod.parameterType(eventParameter.position()); if (Types.containsTypeVariable(observedType)) { - Map resolvedTypeVariables = Types + Map resolvedTypeVariables = Types .resolvedTypeVariables(declaringBean.getImplClazz(), declaringBean.getDeployment()) .getOrDefault(observerMethod.declaringClass(), Collections.emptyMap()); observedType = Types.resolveTypeParam(observedType, resolvedTypeVariables, 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 08462d17a133b..d385a31f874c0 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 @@ -480,7 +480,7 @@ private void processDecorator(DecoratorInfo decorator, BeanInfo bean, Type provi // The delegate type can declare type parameters // For example @Delegate Converter should result in a T -> String mapping List typeParameters = delegateTypeClass.typeParameters(); - Map resolvedTypeParameters = Collections.emptyMap(); + Map resolvedTypeParameters = Collections.emptyMap(); if (!typeParameters.isEmpty()) { resolvedTypeParameters = new HashMap<>(); // The delegate type can be used to infer the parameter types @@ -488,7 +488,7 @@ private void processDecorator(DecoratorInfo decorator, BeanInfo bean, Type provi if (delegateType.kind() == Kind.PARAMETERIZED_TYPE) { List typeArguments = delegateType.asParameterizedType().arguments(); for (int i = 0; i < typeParameters.size(); i++) { - resolvedTypeParameters.put(typeParameters.get(i), typeArguments.get(i)); + resolvedTypeParameters.put(typeParameters.get(i).identifier(), typeArguments.get(i)); } } } 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 c604471397b4b..59202d6cdf3f8 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,7 +384,7 @@ static List getResolvedParameters(ClassInfo classInfo, MethodInfo method, return getResolvedParameters(classInfo, Collections.emptyMap(), method, index); } - static List getResolvedParameters(ClassInfo classInfo, Map resolvedMap, + static List getResolvedParameters(ClassInfo classInfo, Map resolvedMap, MethodInfo method, IndexView index) { List typeParameters = classInfo.typeParameters(); // E.g. Foo, T, List @@ -414,12 +414,13 @@ static List getResolvedParameters(ClassInfo classInfo, Map getTypeClosure(ClassInfo classInfo, AnnotationTarget producerFieldOrMethod, - Map resolvedTypeParameters, - BeanDeployment beanDeployment, BiConsumer> resolvedTypeVariablesConsumer) { + Map resolvedTypeParameters, + BeanDeployment beanDeployment, BiConsumer> resolvedTypeVariablesConsumer) { Set types = new HashSet<>(); List typeParameters = classInfo.typeParameters(); - if (typeParameters.isEmpty() || !typeParameters.stream().allMatch(resolvedTypeParameters::containsKey)) { + if (typeParameters.isEmpty() + || !typeParameters.stream().allMatch(it -> resolvedTypeParameters.containsKey(it.identifier()))) { // Not a parameterized type or a raw type types.add(Type.create(classInfo.name(), Kind.CLASS)); } else { @@ -427,7 +428,7 @@ static Set getTypeClosure(ClassInfo classInfo, AnnotationTarget producerFi Type[] typeParams = new Type[typeParameters.size()]; boolean skipThisType = false; for (int i = 0; i < typeParameters.size(); i++) { - typeParams[i] = resolvedTypeParameters.get(typeParameters.get(i)); + typeParams[i] = resolvedTypeParameters.get(typeParameters.get(i).identifier()); // this should only be the case for producers; wildcard is not a legal bean type // see https://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#legal_bean_types if (typeParams[i].kind().equals(Kind.WILDCARD_TYPE) && producerFieldOrMethod != null) { @@ -440,9 +441,9 @@ static Set getTypeClosure(ClassInfo classInfo, AnnotationTarget producerFi } } if (resolvedTypeVariablesConsumer != null) { - Map resolved = new HashMap<>(); + Map resolved = new HashMap<>(); for (int i = 0; i < typeParameters.size(); i++) { - resolved.put(typeParameters.get(i), typeParams[i]); + resolved.put(typeParameters.get(i).identifier(), typeParams[i]); } resolvedTypeVariablesConsumer.accept(classInfo, resolved); } @@ -457,7 +458,7 @@ static Set getTypeClosure(ClassInfo classInfo, AnnotationTarget producerFi } ClassInfo interfaceClassInfo = getClassByName(beanDeployment.getBeanArchiveIndex(), interfaceType.name()); if (interfaceClassInfo != null) { - Map resolved = Collections.emptyMap(); + Map resolved = Collections.emptyMap(); if (Kind.PARAMETERIZED_TYPE.equals(interfaceType.kind())) { resolved = buildResolvedMap(interfaceType.asParameterizedType().arguments(), interfaceClassInfo.typeParameters(), resolvedTypeParameters, beanDeployment.getBeanArchiveIndex()); @@ -470,7 +471,7 @@ static Set getTypeClosure(ClassInfo classInfo, AnnotationTarget producerFi if (classInfo.superClassType() != null) { ClassInfo superClassInfo = getClassByName(beanDeployment.getBeanArchiveIndex(), classInfo.superName()); if (superClassInfo != null) { - Map resolved = Collections.emptyMap(); + Map resolved = Collections.emptyMap(); if (Kind.PARAMETERIZED_TYPE.equals(classInfo.superClassType().kind())) { resolved = buildResolvedMap(classInfo.superClassType().asParameterizedType().arguments(), superClassInfo.typeParameters(), @@ -509,9 +510,9 @@ static Set getDelegateTypeClosure(InjectionPointInfo delegateInjectionPoin return types; } - static Map> resolvedTypeVariables(ClassInfo classInfo, + static Map> resolvedTypeVariables(ClassInfo classInfo, BeanDeployment beanDeployment) { - Map> resolvedTypeVariables = new HashMap<>(); + Map> resolvedTypeVariables = new HashMap<>(); getTypeClosure(classInfo, null, Collections.emptyMap(), beanDeployment, resolvedTypeVariables::put); return resolvedTypeVariables; } @@ -540,26 +541,27 @@ static Set restrictBeanTypes(Set types, Collection Map buildResolvedMap(List resolvedArguments, + static Map buildResolvedMap(List resolvedArguments, List typeVariables, - Map resolvedTypeParameters, IndexView index) { - Map resolvedMap = new HashMap<>(); + Map resolvedTypeParameters, IndexView index) { + Map resolvedMap = new HashMap<>(); for (int i = 0; i < resolvedArguments.size(); i++) { - resolvedMap.put(typeVariables.get(i), resolveTypeParam(resolvedArguments.get(i), resolvedTypeParameters, index)); + resolvedMap.put(typeVariables.get(i).identifier(), + resolveTypeParam(resolvedArguments.get(i), resolvedTypeParameters, index)); } return resolvedMap; } - static Type resolveTypeParam(Type typeParam, Map resolvedTypeParameters, IndexView index) { + static Type resolveTypeParam(Type typeParam, Map resolvedTypeParameters, IndexView index) { if (typeParam.kind() == Kind.TYPE_VARIABLE) { - return resolvedTypeParameters.getOrDefault(typeParam, typeParam); + return resolvedTypeParameters.getOrDefault(typeParam.asTypeVariable().identifier(), typeParam); } else if (typeParam.kind() == Kind.PARAMETERIZED_TYPE) { ParameterizedType parameterizedType = typeParam.asParameterizedType(); ClassInfo classInfo = getClassByName(index, parameterizedType.name()); if (classInfo != null) { List typeParameters = classInfo.typeParameters(); List arguments = parameterizedType.arguments(); - Map resolvedMap = buildResolvedMap(arguments, typeParameters, + Map resolvedMap = buildResolvedMap(arguments, typeParameters, resolvedTypeParameters, index); Type[] typeParams = new Type[typeParameters.size()]; for (int i = 0; i < typeParameters.size(); i++) { diff --git a/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/TypesTest.java b/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/TypesTest.java index 787085e203cb2..b24c18e3cba06 100644 --- a/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/TypesTest.java +++ b/independent-projects/arc/processor/src/test/java/io/quarkus/arc/processor/TypesTest.java @@ -18,7 +18,6 @@ import org.jboss.jandex.ParameterizedType; import org.jboss.jandex.Type; import org.jboss.jandex.Type.Kind; -import org.jboss.jandex.TypeVariable; import org.junit.jupiter.api.Test; public class TypesTest { @@ -31,7 +30,7 @@ public void testGetTypeClosure() throws IOException { DotName fooName = DotName.createSimple(Foo.class.getName()); DotName producerName = DotName.createSimple(Producer.class.getName()); ClassInfo fooClass = index.getClassByName(fooName); - Map> resolvedTypeVariables = new HashMap<>(); + Map> resolvedTypeVariables = new HashMap<>(); BeanDeployment dummyDeployment = BeanProcessor.builder().setBeanArchiveIndex(index).build().getBeanDeployment(); // Baz, Foo, Object @@ -46,7 +45,7 @@ public void testGetTypeClosure() throws IOException { null))); assertEquals(resolvedTypeVariables.size(), 1); assertTrue(resolvedTypeVariables.containsKey(fooClass)); - assertEquals(resolvedTypeVariables.get(fooClass).get(fooClass.typeParameters().get(0)), + assertEquals(resolvedTypeVariables.get(fooClass).get(fooClass.typeParameters().get(0).identifier()), Type.create(DotName.createSimple(String.class.getName()), Kind.CLASS)); resolvedTypeVariables.clear();